Skip to content

Commit e696b86

Browse files
authored
Merge pull request #51 from TeamLearningFlow/develop
[FEAT] 회원가입, 로그인 기능 수정, Deploy push
2 parents e8750da + b491a38 commit e696b86

File tree

18 files changed

+186
-175
lines changed

18 files changed

+186
-175
lines changed

build.gradle

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ dependencies {
4949
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
5050
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'
5151

52-
// Redis
53-
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
54-
5552
// 템플릿 엔진
5653
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
5754

src/main/generated/learningFlow/learningFlow_BE/domain/QUser.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ public class QUser extends EntityPathBase<User> {
3131

3232
public final StringPath email = createString("email");
3333

34-
public final EnumPath<learningFlow.learningFlow_BE.domain.enums.Gender> gender = createEnum("gender", learningFlow.learningFlow_BE.domain.enums.Gender.class);
35-
3634
public final QImage image;
3735

3836
public final BooleanPath inactive = createBoolean("inactive");

src/main/java/learningFlow/learningFlow_BE/config/redis/RedisConfig.java

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/main/java/learningFlow/learningFlow_BE/config/security/SecurityConfig.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,18 @@ public SecurityFilterChain filterChain(HttpSecurity http, JwtAuthenticationFilte
5252
"/find/**",
5353
"/reset-password",
5454
"/search/**",
55-
"/home/**",
55+
"/",
5656
"/collections/{collectionId:[\\d]+}"
5757
).permitAll()
5858
.requestMatchers(
59-
"/register", "/register/complete", "/login", "/login/google", "/oauth2/**", "/logout/**").permitAll()
59+
"/register", "/register/complete", "/login", "/login/google", "/oauth2/**").permitAll()
6060
.requestMatchers("/admin/**").hasRole("ADMIN")
61-
.requestMatchers("/user/**", "/resources/**", "/collections/{collectionId}/bookmark").authenticated()
61+
.requestMatchers("/user/**", "/resources/**", "/collections/{collectionId}/bookmark", "/logout/**").authenticated()
6262
.anyRequest().permitAll()
6363
)
6464
.formLogin(AbstractHttpConfigurer::disable)
65+
.logout(AbstractHttpConfigurer::disable // 기본 로그아웃 처리 비활성화
66+
)
6567
.oauth2Login(oauth2 -> oauth2
6668
.userInfoEndpoint(userInfo -> userInfo
6769
.userService(OAuth2UserAuthenticationService))

src/main/java/learningFlow/learningFlow_BE/converter/UserConverter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public static UserInfoDTO convertToUserInfoDTO(User user) {
2828
.email(user.getEmail())
2929
.job(user.getJob())
3030
.interestFields(user.getInterestFields())
31-
.gender(user.getGender())
3231
.preferType(user.getPreferType())
3332
.profileImageUrl(user.getImage() != null ? user.getImage().getImageURL() : null)
3433
.build();

src/main/java/learningFlow/learningFlow_BE/domain/User.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@ public class User extends BaseEntity {
4949
@Column(name = "interest_field", nullable = false)
5050
private List<InterestField> interestFields;
5151

52-
@Enumerated(EnumType.STRING)
53-
@Column(nullable = false)
54-
private Gender gender;
55-
5652
@Enumerated(EnumType.STRING)
5753
@Column(nullable = false)
5854
private Role role;
@@ -139,10 +135,6 @@ public void updateInterestFields(List<InterestField> interestFields) {
139135
// this.birthDay = birthDay;
140136
// }
141137

142-
public void updateGender(Gender gender) {
143-
this.gender = gender;
144-
}
145-
146138
public void updatePreferType(MediaType preferType) {
147139
this.preferType = preferType;
148140
}

src/main/java/learningFlow/learningFlow_BE/domain/enums/Gender.java

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,30 @@
11
package learningFlow.learningFlow_BE.security.handler;
22

3+
import jakarta.servlet.http.Cookie;
34
import jakarta.servlet.http.HttpServletRequest;
45
import jakarta.servlet.http.HttpServletResponse;
5-
import learningFlow.learningFlow_BE.security.jwt.JwtTokenProvider;
66
import lombok.RequiredArgsConstructor;
77
import lombok.extern.slf4j.Slf4j;
8-
import org.springframework.data.redis.core.RedisTemplate;
98
import org.springframework.security.core.Authentication;
9+
import org.springframework.security.core.context.SecurityContextHolder;
1010
import org.springframework.security.web.authentication.logout.LogoutHandler;
1111
import org.springframework.stereotype.Component;
12-
import org.springframework.util.StringUtils;
13-
14-
import java.util.concurrent.TimeUnit;
1512

1613
@Slf4j
1714
@Component
1815
@RequiredArgsConstructor
1916
public class JwtLogoutHandler implements LogoutHandler {
2017

21-
private final RedisTemplate<String, String> redisTemplate;
22-
private final JwtTokenProvider jwtTokenProvider;
23-
2418
@Override
2519
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
26-
String jwt = getJwtFromRequest(request);
27-
addToBlacklist(jwt);
28-
}
20+
// SecurityContext 초기화
21+
SecurityContextHolder.clearContext();
2922

30-
public void addToBlacklist(String token) {
31-
log.info("토큰 블랙 리스트 추가 시도");
32-
33-
if (StringUtils.hasText(token) && jwtTokenProvider.validateToken(token)) {
34-
log.info("유효한 토큰 발견: {}", token);
35-
long expiration = jwtTokenProvider.getExpirationFromToken(token);
36-
long now = System.currentTimeMillis();
37-
long remainingTime = (expiration - now) / 1000;
38-
39-
redisTemplate.opsForValue()
40-
.set("BLACKLIST:" + token, "true", remainingTime, TimeUnit.SECONDS);
41-
log.info("토큰이 블랙리스트에 추가됨");
42-
} else {
43-
log.info("유효하지 않은 토큰");
44-
throw new RuntimeException("유효하지 않은 토큰입니다.");
45-
}
46-
}
23+
// Authorization 헤더 제거
24+
response.setHeader("Authorization", null);
25+
response.setHeader("Refresh-Token", null);
4726

48-
private String getJwtFromRequest(HttpServletRequest request) {
49-
String bearerToken = request.getHeader("Authorization");
50-
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
51-
return bearerToken.substring(7);
52-
}
53-
return null;
27+
log.info("로그아웃 처리 완료: {}",
28+
authentication != null ? authentication.getName() : "Unknown user");
5429
}
5530
}

src/main/java/learningFlow/learningFlow_BE/security/jwt/JwtAuthenticationFilter.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import learningFlow.learningFlow_BE.service.user.CustomUserDetailsService;
1010
import lombok.RequiredArgsConstructor;
1111
import lombok.extern.slf4j.Slf4j;
12-
import org.springframework.data.redis.core.RedisTemplate;
1312
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
1413
import org.springframework.security.core.context.SecurityContextHolder;
1514
import org.springframework.security.core.userdetails.UserDetails;
@@ -26,7 +25,6 @@
2625
public class JwtAuthenticationFilter extends OncePerRequestFilter {
2726
private final JwtTokenProvider jwtTokenProvider;
2827
private final CustomUserDetailsService customUserDetailsService;
29-
private final RedisTemplate<String, String> redisTemplate;
3028

3129
@Override
3230
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
@@ -38,15 +36,6 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
3836
if (jwtTokenProvider.validateToken(jwt)) {
3937
log.info("유효한 Access Token");
4038

41-
if (!request.getRequestURI().equals("/logout/test")) {
42-
Boolean isBlacklisted = redisTemplate.hasKey("BLACKLIST:" + jwt);
43-
log.info("블랙리스트 체크 결과: {}", isBlacklisted);
44-
45-
if (Boolean.TRUE.equals(isBlacklisted)) {
46-
throw new RuntimeException("이미 로그아웃된 토큰입니다.");
47-
}
48-
}
49-
5039
String email = jwtTokenProvider.getEmailFromToken(jwt);
5140
log.info("토큰에서 추출한 이메일: {}", email);
5241

@@ -128,7 +117,7 @@ private boolean isPermitAllUrl(String requestURI) {
128117
requestURI.startsWith("/webjars") ||
129118
requestURI.startsWith("/find") ||
130119
requestURI.startsWith("/search") ||
131-
requestURI.startsWith("/home") ||
120+
requestURI.startsWith("/") ||
132121
requestURI.equals("/reset-password");
133122
}
134123
}

src/main/java/learningFlow/learningFlow_BE/service/auth/common/UserVerificationEmailService.java

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,21 +103,83 @@ public void sendVerificationEmail(String email, String token) {
103103
}
104104

105105
public void sendPasswordResetEmail(String email, String token) {
106+
106107
try {
107-
SimpleMailMessage message = new SimpleMailMessage();
108-
message.setTo(email);
109-
message.setSubject("[OnBoarding] 비밀번호 재설정");
110-
message.setText(
111-
"안녕하세요, OnBoarding입니다.\n\n" +
112-
"비밀번호 재설정을 위해 아래 링크를 클릭해주세요:\n\n" +
113-
baseUrl + "/reset-password?token=" + token + "\n\n" +
114-
"이 링크는 24시간 동안 유효합니다.\n" +
115-
"본인이 요청하지 않은 경우 이 이메일을 무시해주세요."
116-
);
108+
MimeMessage message = emailSender.createMimeMessage();
109+
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
110+
111+
helper.setTo(email);
112+
helper.setSubject("[OnBoarding] 비밀번호 재설정");
117113

114+
String htmlContent = """
115+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
116+
<html xmlns="http://www.w3.org/1999/xhtml">
117+
<head>
118+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
119+
<title></title>
120+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
121+
<meta name="viewport" content="width=device-width" />
122+
<style type="text/css">
123+
@media only screen and (min-width: 620px) {
124+
.wrapper { min-width: 600px !important; }
125+
}
126+
body { margin: 0; padding: 0; -webkit-text-size-adjust: 100%%; }
127+
.wrapper { background-color: #f0f0f0; }
128+
.header { background-color: #5e52ff; }
129+
.btn {
130+
display: inline-block;
131+
padding: 12px 24px;
132+
background-color: #5e52ff;
133+
color: #ffffff;
134+
text-decoration: none;
135+
border-radius: 4px;
136+
font-weight: bold;
137+
}
138+
</style>
139+
</head>
140+
<body>
141+
<table class="wrapper" style="border-collapse: collapse; width: 100%%;">
142+
<tr>
143+
<td align="center">
144+
<div style="max-width: 600px; margin: 0 auto;">
145+
<div style="text-align: center; padding: 20px;">
146+
<img src="https://i.imgur.com/qqvcW0H.jpg" alt="OnBoarding" style="max-width: 369px; width: 100%%;"/>
147+
</div>
148+
149+
<div style="background-color: #ffffff; padding: 40px 20px; text-align: center;">
150+
<h1 style="color: #565656; font-size: 28px; margin-bottom: 20px;">
151+
비밀번호 재설정을 위해 메일을 인증해주세요
152+
</h1>
153+
154+
<p style="color: #787778; font-size: 16px; line-height: 24px; margin-bottom: 30px;">
155+
안녕하세요, OnBoarding입니다.<br/>
156+
비밀번호 재설정을 위해 메일을 인증해주세요<br/>
157+
버튼을 누르면 자동으로 인증 후 비밀번호 재설정 페이지로 이동합니다.
158+
</p>
159+
160+
<a href="%s/change-password?token=%s"
161+
class="btn"
162+
style="background-color: #5e52ff; color: #ffffff; text-decoration: none; padding: 12px 24px; border-radius: 4px; font-weight: bold; display: inline-block; margin: 20px 0;">
163+
이메일 인증하기
164+
</a>
165+
166+
<p style="color: #787778; font-size: 14px; font-style: italic; margin-top: 30px;">
167+
이 메일은 24시간 동안 유효합니다.<br/>
168+
본인이 요청하지 않은 경우, 이 메일을 무시해주세요.
169+
</p>
170+
</div>
171+
</div>
172+
</td>
173+
</tr>
174+
</table>
175+
</body>
176+
</html>
177+
""".formatted(baseUrl, token);
178+
179+
helper.setText(htmlContent, true);
118180
emailSender.send(message);
119-
log.info("비밀번호 재설정 이메일 발송 완료: {}", email);
120-
} catch (Exception e) {
181+
log.info("이메일 인증 메일 발송 완료: {}", email);
182+
} catch (MessagingException e) {
121183
log.error("이메일 발송 실패: {}", e.getMessage());
122184
throw new RuntimeException("이메일 발송에 실패했습니다.");
123185
}

0 commit comments

Comments
 (0)