
--- src/main/java/com/takensoft/cms/mber/dto/LoginDTO.java
+++ src/main/java/com/takensoft/cms/mber/dto/LoginDTO.java
... | ... | @@ -26,4 +26,5 @@ |
26 | 26 |
@NotNull |
27 | 27 |
private String pswd; // 비밀번호 |
28 | 28 |
private String refreshToken; // refreshToken 정보 |
29 |
+ private String lgnReqPage; // 로그인 요청 페이지 (관리자: A, 사용자: U) |
|
29 | 30 |
} |
--- src/main/java/com/takensoft/common/config/SecurityConfig.java
+++ src/main/java/com/takensoft/common/config/SecurityConfig.java
... | ... | @@ -11,7 +11,9 @@ |
11 | 11 |
import com.takensoft.common.exception.CustomAccessDenieHandler; |
12 | 12 |
import com.takensoft.common.exception.CustomAuthenticationEntryPoint; |
13 | 13 |
import com.takensoft.common.util.JWTUtil; |
14 |
+import com.takensoft.common.util.LoginUtil; |
|
14 | 15 |
import com.takensoft.common.util.SessionUtil; |
16 |
+import com.takensoft.common.verify.service.Impl.EmailServiceImpl; |
|
15 | 17 |
import org.springframework.beans.factory.annotation.Value; |
16 | 18 |
import org.springframework.context.annotation.Bean; |
17 | 19 |
import org.springframework.context.annotation.Configuration; |
... | ... | @@ -57,7 +59,9 @@ |
57 | 59 |
private final AppConfig appConfig; |
58 | 60 |
private final LoginModeService loginModeService; |
59 | 61 |
private final LoginPolicyService loginPolicyService; |
62 |
+ private final EmailServiceImpl emailServiceImpl; |
|
60 | 63 |
private final SessionUtil sessionUtil; |
64 |
+ private final LoginUtil loginUtil; |
|
61 | 65 |
|
62 | 66 |
private static String FRONT_URL; // 프론트 접근 허용 URL |
63 | 67 |
private static long JWT_ACCESSTIME; // access 토큰 유지 시간 |
... | ... | @@ -80,7 +84,8 @@ |
80 | 84 |
*/ |
81 | 85 |
public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil, RefreshTokenService refreshTokenService, CntxtPthService cntxtPthService, AccesCtrlService accesCtrlService, AppConfig appConfig, |
82 | 86 |
LgnHstryService lgnHstryService, CustomAuthenticationEntryPoint authenticationEntryPoint, CustomAccessDenieHandler accessDenieHandler, HttpRequestUtil httpRequestUtil, |
83 |
- LoginModeService loginModeService, LoginPolicyService loginPolicyService, SessionUtil sessionUtil, @Value("${front.url}") String fUrl, @Value("${jwt.accessTime}") long aTime, @Value("${jwt.refreshTime}") long rTime, @Value("${cookie.time}") int ctime, RedisTemplate<String, String> redisTemplate) { |
|
87 |
+ LoginModeService loginModeService, LoginPolicyService loginPolicyService, EmailServiceImpl emailServiceImpl, SessionUtil sessionUtil, @Value("${front.url}") String fUrl, @Value("${jwt.accessTime}") long aTime, @Value("${jwt.refreshTime}") long rTime, @Value("${cookie.time}") int ctime, RedisTemplate<String, String> redisTemplate, |
|
88 |
+ LoginUtil loginUtil) { |
|
84 | 89 |
|
85 | 90 |
this.authenticationConfiguration = authenticationConfiguration; |
86 | 91 |
this.refreshTokenService = refreshTokenService; |
... | ... | @@ -94,12 +99,14 @@ |
94 | 99 |
this.appConfig = appConfig; |
95 | 100 |
this.loginModeService = loginModeService; |
96 | 101 |
this.loginPolicyService = loginPolicyService; |
102 |
+ this.emailServiceImpl = emailServiceImpl; |
|
97 | 103 |
this.sessionUtil = sessionUtil; |
98 | 104 |
this.FRONT_URL = fUrl; |
99 | 105 |
this.JWT_ACCESSTIME = aTime; |
100 | 106 |
this.JWT_REFRESHTIME = rTime; |
101 | 107 |
this.COOKIE_TIME = ctime; |
102 | 108 |
this.redisTemplate = redisTemplate; |
109 |
+ this.loginUtil = loginUtil; |
|
103 | 110 |
} |
104 | 111 |
|
105 | 112 |
/** |
... | ... | @@ -180,7 +187,8 @@ |
180 | 187 |
|
181 | 188 |
// 로그인 필터 |
182 | 189 |
http.addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil, refreshTokenService, lgnHstryService, httpRequestUtil, |
183 |
- loginModeService, loginPolicyService, sessionUtil, JWT_ACCESSTIME, JWT_REFRESHTIME, COOKIE_TIME, redisTemplate), UsernamePasswordAuthenticationFilter.class); |
|
190 |
+ loginModeService, loginPolicyService, emailServiceImpl, sessionUtil, JWT_ACCESSTIME, JWT_REFRESHTIME, COOKIE_TIME, redisTemplate, |
|
191 |
+ loginUtil), UsernamePasswordAuthenticationFilter.class); |
|
184 | 192 |
|
185 | 193 |
return http.build(); |
186 | 194 |
} |
--- src/main/java/com/takensoft/common/filter/LoginFilter.java
+++ src/main/java/com/takensoft/common/filter/LoginFilter.java
... | ... | @@ -12,7 +12,10 @@ |
12 | 12 |
import com.takensoft.common.exception.FilterExceptionHandler; |
13 | 13 |
import com.takensoft.common.util.HttpRequestUtil; |
14 | 14 |
import com.takensoft.common.util.JWTUtil; |
15 |
+import com.takensoft.common.util.LoginUtil; |
|
15 | 16 |
import com.takensoft.common.util.SessionUtil; |
17 |
+import com.takensoft.common.verify.service.Impl.EmailServiceImpl; |
|
18 |
+import com.takensoft.common.verify.vo.EmailVO; |
|
16 | 19 |
import jakarta.servlet.http.HttpSession; |
17 | 20 |
import lombok.SneakyThrows; |
18 | 21 |
import org.springframework.beans.factory.annotation.Value; |
... | ... | @@ -55,7 +58,9 @@ |
55 | 58 |
private final HttpRequestUtil httpRequestUtil; |
56 | 59 |
private final LoginModeService loginModeService; |
57 | 60 |
private final LoginPolicyService loginPolicyService; |
61 |
+ private final EmailServiceImpl emailServiceImpl; |
|
58 | 62 |
private final SessionUtil sessionUtil; |
63 |
+ private final LoginUtil loginUtil; |
|
59 | 64 |
|
60 | 65 |
private static long JWT_ACCESSTIME; // access 토큰 유지 시간 |
61 | 66 |
private static long JWT_REFRESHTIME; // refresh 토큰 유지 시간 |
... | ... | @@ -72,7 +77,8 @@ |
72 | 77 |
* LoginFilter 생성자 |
73 | 78 |
*/ |
74 | 79 |
public LoginFilter(AuthenticationManager authenticationManager, JWTUtil jwtUtil, RefreshTokenService refreshTokenService, LgnHstryService lgnHstryService, HttpRequestUtil httpRequestUtil, |
75 |
- LoginModeService loginModeService,LoginPolicyService loginPolicyService,SessionUtil sessionUtil, @Value("${jwt.accessTime}")long aTime, @Value("${jwt.refreshTime}")long rTime, @Value("${cookie.time}")int ctime, RedisTemplate<String, String> redisTemplate) { |
|
80 |
+ LoginModeService loginModeService,LoginPolicyService loginPolicyService, EmailServiceImpl emailServiceImpl, SessionUtil sessionUtil, @Value("${jwt.accessTime}")long aTime, @Value("${jwt.refreshTime}")long rTime, @Value("${cookie.time}")int ctime, RedisTemplate<String, String> redisTemplate, |
|
81 |
+ LoginUtil loginUtil) { |
|
76 | 82 |
this.authenticationManager = authenticationManager; |
77 | 83 |
this.jwtUtil = jwtUtil; |
78 | 84 |
this.refreshTokenService = refreshTokenService; |
... | ... | @@ -80,12 +86,13 @@ |
80 | 86 |
this.httpRequestUtil = httpRequestUtil; |
81 | 87 |
this.loginModeService = loginModeService; |
82 | 88 |
this.loginPolicyService = loginPolicyService; |
89 |
+ this.emailServiceImpl = emailServiceImpl; |
|
83 | 90 |
this.sessionUtil = sessionUtil; |
84 | 91 |
this.JWT_ACCESSTIME = aTime; |
85 | 92 |
this.JWT_REFRESHTIME = rTime; |
86 | 93 |
this.COOKIE_TIME = ctime; |
87 | 94 |
this.redisTemplate = redisTemplate; |
88 |
- |
|
95 |
+ this.loginUtil = loginUtil; |
|
89 | 96 |
|
90 | 97 |
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/mbr/loginProc.json","POST")); |
91 | 98 |
} |
... | ... | @@ -106,6 +113,7 @@ |
106 | 113 |
// 클라이언트에서 요청한 아이디와 비밀번호 추출 |
107 | 114 |
String lgnId = login.getLgnId(); |
108 | 115 |
String pswd = login.getPswd(); |
116 |
+ req.setAttribute("lgnReqPage", login.getLgnReqPage()); |
|
109 | 117 |
|
110 | 118 |
// 스프링 시큐리티에서 username과 password를 검증하기 위해서는 token에 담아야 함 |
111 | 119 |
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(lgnId, pswd, null); |
... | ... | @@ -127,71 +135,102 @@ |
127 | 135 |
@SneakyThrows |
128 | 136 |
@Override |
129 | 137 |
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication authentication) throws IOException { |
138 |
+ Map<String, Object> result = new HashMap<>(); |
|
139 |
+ |
|
130 | 140 |
MberVO mber = (MberVO) authentication.getPrincipal(); |
131 | 141 |
|
132 |
- // 로그인 이력 등록 |
|
133 |
- LgnHstryVO lgnHstryVO = new LgnHstryVO(); |
|
134 |
- lgnHstryVO.setLgnId(mber.getLgnId()); |
|
135 |
- if(mber.getAuthorities().stream().anyMatch(role -> role.getAuthority().equals("ROLE_ADMIN"))) { |
|
136 |
- lgnHstryVO.setLgnType("0"); |
|
137 |
- } else { |
|
138 |
- lgnHstryVO.setLgnType("1"); |
|
139 |
- } |
|
140 |
- lgnHstryVO.setCntnIp(httpRequestUtil.getIp(req)); |
|
141 |
- lgnHstryVO.setCntnOperSys(httpRequestUtil.getOS(httpRequestUtil.getUserAgent(req))); |
|
142 |
- lgnHstryVO.setDeviceNm(httpRequestUtil.getDevice(httpRequestUtil.getUserAgent(req))); |
|
143 |
- lgnHstryVO.setBrwsrNm(httpRequestUtil.getBrowser(httpRequestUtil.getUserAgent(req))); |
|
144 |
- lgnHstryService.LgnHstrySave(lgnHstryVO); |
|
142 |
+ String lgnReqPage = (String) req.getAttribute("lgnReqPage"); |
|
143 |
+ // 로그인 요청 페이지가 관리자 페이지일 경우 |
|
144 |
+ if("A".equals(lgnReqPage)) { |
|
145 |
+ // 관리자 권한이 있는지 확인 |
|
146 |
+ if(mber.getAuthorities().stream().anyMatch(role -> role.getAuthority().equals("ROLE_ADMIN"))) { |
|
147 |
+ EmailVO emailVO = new EmailVO().builder() |
|
148 |
+ .email(mber.getEml()) |
|
149 |
+ .build(); |
|
150 |
+ emailServiceImpl.sendEmailVerifyCode(emailVO); |
|
151 |
+ res.setContentType("application/json;charset=UTF-8"); |
|
152 |
+ res.setStatus(HttpStatus.OK.value()); |
|
153 |
+ result.put("mbrId", mber.getMbrId()); |
|
154 |
+ result.put("email", mber.getEml()); |
|
145 | 155 |
|
146 |
- // 로그인 방식 확인 JWT or SESSION |
|
147 |
- String loginType = loginModeService.getLoginMode(); |
|
156 |
+ res.setContentType("application/json;charset=UTF-8"); |
|
157 |
+ res.setStatus(HttpStatus.OK.value()); |
|
148 | 158 |
|
149 |
- // 토큰 생성(access, refresh) |
|
150 |
- String accessToken = jwtUtil.createJwt("Authorization", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_ACCESSTIME); |
|
151 |
- String refreshToken = jwtUtil.createJwt("refresh", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_REFRESHTIME); |
|
159 |
+ new ObjectMapper().writeValue(res.getOutputStream(), result); |
|
160 |
+ } else { |
|
161 |
+ // 관리자 권한이 없는 경우 접근 권한이 없습니다 |
|
162 |
+ res.setContentType("application/json;charset=UTF-8"); |
|
163 |
+ res.setStatus(HttpStatus.FORBIDDEN.value()); |
|
152 | 164 |
|
153 |
- // refreshToken이 현재 IP와 계정으로 등록되어 있는지 확인 |
|
154 |
- RefreshTknVO refresh = new RefreshTknVO(); |
|
155 |
- refresh.setMbrId(mber.getMbrId()); |
|
156 |
- |
|
157 |
- // refresh 토큰이 현재 아이피와 아이디로 DB에 등록 되어 있다면 |
|
158 |
- if(refreshTokenService.findByCheckRefresh(req, refresh)) { |
|
159 |
- refreshTokenService.delete(req, refresh); |
|
160 |
- } |
|
161 |
- // refreshToken DB 저장 |
|
162 |
- refresh.setToken(refreshToken); |
|
163 |
- |
|
164 |
- |
|
165 |
- if (loginType.equals("S")) { |
|
166 |
- HttpSession session = req.getSession(true); |
|
167 |
- session.setAttribute("JWT_TOKEN", accessToken); |
|
168 |
- |
|
169 |
- // 중복 로그인 비허용일 때 기존 세션 만료 |
|
170 |
- if (!loginPolicyService.getPolicy()) { |
|
171 |
- sessionUtil.registerSession(mber.getMbrId(), session); |
|
165 |
+ result.put("message", "접근 권한이 없습니다."); |
|
166 |
+ new ObjectMapper().writeValue(res.getOutputStream(), result); |
|
172 | 167 |
} |
173 |
- Map<String, Object> result = new HashMap<>(); |
|
174 |
- result.put("mbrId", mber.getMbrId()); |
|
175 |
- result.put("mbrNm", mber.getMbrNm()); |
|
176 |
- result.put("roles", mber.getAuthorList()); |
|
177 |
- |
|
178 |
- res.setContentType("application/json;charset=UTF-8"); |
|
179 |
- res.setStatus(HttpStatus.OK.value()); |
|
180 |
- |
|
181 |
- ObjectMapper mapper = new ObjectMapper(); |
|
182 |
- res.getOutputStream().write(mapper.writeValueAsBytes(result)); |
|
183 | 168 |
} else { |
184 |
- res.setHeader("Authorization", accessToken); |
|
185 |
- res.addCookie(jwtUtil.createCookie("refresh", refreshToken, COOKIE_TIME)); |
|
186 |
- |
|
187 |
- // 중복 로그인 비허용일 때 Redis 저장 |
|
188 |
- if (!loginPolicyService.getPolicy()) { |
|
189 |
- redisTemplate.delete("jwt:" + mber.getMbrId()); |
|
190 |
- redisTemplate.opsForValue().set("jwt:" + mber.getMbrId(), accessToken, JWT_ACCESSTIME, TimeUnit.MILLISECONDS); |
|
191 |
- } |
|
169 |
+ loginUtil.successLogin(mber, req, res); |
|
170 |
+// // 로그인 이력 등록 |
|
171 |
+// LgnHstryVO lgnHstryVO = new LgnHstryVO(); |
|
172 |
+// lgnHstryVO.setLgnId(mber.getLgnId()); |
|
173 |
+// if (mber.getAuthorities().stream().anyMatch(role -> role.getAuthority().equals("ROLE_ADMIN"))) { |
|
174 |
+// lgnHstryVO.setLgnType("0"); |
|
175 |
+// } else { |
|
176 |
+// lgnHstryVO.setLgnType("1"); |
|
177 |
+// } |
|
178 |
+// lgnHstryVO.setCntnIp(httpRequestUtil.getIp(req)); |
|
179 |
+// lgnHstryVO.setCntnOperSys(httpRequestUtil.getOS(httpRequestUtil.getUserAgent(req))); |
|
180 |
+// lgnHstryVO.setDeviceNm(httpRequestUtil.getDevice(httpRequestUtil.getUserAgent(req))); |
|
181 |
+// lgnHstryVO.setBrwsrNm(httpRequestUtil.getBrowser(httpRequestUtil.getUserAgent(req))); |
|
182 |
+// lgnHstryService.LgnHstrySave(lgnHstryVO); |
|
183 |
+// |
|
184 |
+// // 로그인 방식 확인 JWT or SESSION |
|
185 |
+// String loginType = loginModeService.getLoginMode(); |
|
186 |
+// |
|
187 |
+// // 토큰 생성(access, refresh) |
|
188 |
+// String accessToken = jwtUtil.createJwt("Authorization", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_ACCESSTIME); |
|
189 |
+// String refreshToken = jwtUtil.createJwt("refresh", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_REFRESHTIME); |
|
190 |
+// |
|
191 |
+// // refreshToken이 현재 IP와 계정으로 등록되어 있는지 확인 |
|
192 |
+// RefreshTknVO refresh = new RefreshTknVO(); |
|
193 |
+// refresh.setMbrId(mber.getMbrId()); |
|
194 |
+// |
|
195 |
+// // refresh 토큰이 현재 아이피와 아이디로 DB에 등록 되어 있다면 |
|
196 |
+// if (refreshTokenService.findByCheckRefresh(req, refresh)) { |
|
197 |
+// refreshTokenService.delete(req, refresh); |
|
198 |
+// } |
|
199 |
+// // refreshToken DB 저장 |
|
200 |
+// refresh.setToken(refreshToken); |
|
201 |
+// |
|
202 |
+// |
|
203 |
+// if (loginType.equals("S")) { |
|
204 |
+// HttpSession session = req.getSession(true); |
|
205 |
+// session.setAttribute("JWT_TOKEN", accessToken); |
|
206 |
+// |
|
207 |
+// // 중복 로그인 비허용일 때 기존 세션 만료 |
|
208 |
+// if (!loginPolicyService.getPolicy()) { |
|
209 |
+// sessionUtil.registerSession(mber.getMbrId(), session); |
|
210 |
+// } |
|
211 |
+// Map<String, Object> result = new HashMap<>(); |
|
212 |
+// result.put("mbrId", mber.getMbrId()); |
|
213 |
+// result.put("mbrNm", mber.getMbrNm()); |
|
214 |
+// result.put("roles", mber.getAuthorList()); |
|
215 |
+// |
|
216 |
+// res.setContentType("application/json;charset=UTF-8"); |
|
217 |
+// res.setStatus(HttpStatus.OK.value()); |
|
218 |
+// |
|
219 |
+// ObjectMapper mapper = new ObjectMapper(); |
|
220 |
+// res.getOutputStream().write(mapper.writeValueAsBytes(result)); |
|
221 |
+// } else { |
|
222 |
+// res.setHeader("Authorization", accessToken); |
|
223 |
+// res.addCookie(jwtUtil.createCookie("refresh", refreshToken, COOKIE_TIME)); |
|
224 |
+// |
|
225 |
+// // 중복 로그인 비허용일 때 Redis 저장 |
|
226 |
+// if (!loginPolicyService.getPolicy()) { |
|
227 |
+// redisTemplate.delete("jwt:" + mber.getMbrId()); |
|
228 |
+// redisTemplate.opsForValue().set("jwt:" + mber.getMbrId(), accessToken, JWT_ACCESSTIME, TimeUnit.MILLISECONDS); |
|
229 |
+// } |
|
230 |
+// } |
|
231 |
+// refreshTokenService.saveRefreshToken(req, res, refresh, JWT_REFRESHTIME); |
|
232 |
+// res.setHeader("login-type", loginType); |
|
192 | 233 |
} |
193 |
- refreshTokenService.saveRefreshToken(req, res, refresh, JWT_REFRESHTIME); |
|
194 |
- res.setHeader("login-type", loginType); |
|
195 | 234 |
} |
196 | 235 |
|
197 | 236 |
/** |
--- src/main/java/com/takensoft/common/message/MessageCode.java
+++ src/main/java/com/takensoft/common/message/MessageCode.java
... | ... | @@ -69,6 +69,7 @@ |
69 | 69 |
FILE_UPLOAD_FAIL("file.upload_fail", HttpStatus.INTERNAL_SERVER_ERROR), // 파일 업로드 실패 |
70 | 70 |
|
71 | 71 |
// 이메일 인증 관련 |
72 |
+ EMAIL_SEND_SUCCESS("email.send_success", HttpStatus.OK), // 이메일 발송 성공 |
|
72 | 73 |
EMAIL_SEND_FAIL("email.send_fail", HttpStatus.INTERNAL_SERVER_ERROR), // 이메일 발송 실패 |
73 | 74 |
EMAIL_VERIFY_SUCCESS("email.verify_success", HttpStatus.OK), // 이메일 인증 성공 |
74 | 75 |
EMAIL_VERIFY_EXPIRED("email.verify_expired", HttpStatus.UNAUTHORIZED), // 이메일 인증 만료 |
+++ src/main/java/com/takensoft/common/util/LoginUtil.java
... | ... | @@ -0,0 +1,112 @@ |
1 | +package com.takensoft.common.util; | |
2 | + | |
3 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
4 | +import com.takensoft.cms.loginPolicy.service.LoginModeService; | |
5 | +import com.takensoft.cms.loginPolicy.service.LoginPolicyService; | |
6 | +import com.takensoft.cms.mber.service.LgnHstryService; | |
7 | +import com.takensoft.cms.mber.vo.LgnHstryVO; | |
8 | +import com.takensoft.cms.mber.vo.MberVO; | |
9 | +import com.takensoft.cms.token.service.RefreshTokenService; | |
10 | +import com.takensoft.cms.token.vo.RefreshTknVO; | |
11 | +import jakarta.servlet.http.HttpServletRequest; | |
12 | +import jakarta.servlet.http.HttpServletResponse; | |
13 | +import jakarta.servlet.http.HttpSession; | |
14 | +import lombok.RequiredArgsConstructor; | |
15 | +import org.springframework.beans.factory.annotation.Value; | |
16 | +import org.springframework.data.redis.core.RedisTemplate; | |
17 | +import org.springframework.http.HttpStatus; | |
18 | +import org.springframework.stereotype.Component; | |
19 | + | |
20 | +import java.io.IOException; | |
21 | +import java.util.HashMap; | |
22 | +import java.util.List; | |
23 | +import java.util.Map; | |
24 | +import java.util.concurrent.TimeUnit; | |
25 | + | |
26 | +@Component | |
27 | +@RequiredArgsConstructor | |
28 | +public class LoginUtil { | |
29 | + private final LgnHstryService lgnHstryService; | |
30 | + private final HttpRequestUtil httpRequestUtil; | |
31 | + private final LoginModeService loginModeService; | |
32 | + private final RefreshTokenService refreshTokenService; | |
33 | + private final LoginPolicyService loginPolicyService; | |
34 | + private final JWTUtil jwtUtil; | |
35 | + private final SessionUtil sessionUtil; | |
36 | + private final RedisTemplate<String, String> redisTemplate; | |
37 | + | |
38 | + @Value("${jwt.accessTime}") | |
39 | + private long JWT_ACCESSTIME; | |
40 | + @Value("${jwt.refreshTime}") | |
41 | + private long JWT_REFRESHTIME; | |
42 | + @Value("${cookie.time}") | |
43 | + private int COOKIE_TIME; | |
44 | + | |
45 | + public void successLogin(MberVO mber, HttpServletRequest req, HttpServletResponse res) { | |
46 | + try { | |
47 | + // 로그인 이력 등록 | |
48 | + LgnHstryVO lgnHstryVO = new LgnHstryVO(); | |
49 | + lgnHstryVO.setLgnId(mber.getLgnId()); | |
50 | + lgnHstryVO.setLgnType(mber.getAuthorities().stream().anyMatch(role -> role.getAuthority().equals("ROLE_ADMIN")) ? "0" : "1"); | |
51 | + lgnHstryVO.setCntnIp(httpRequestUtil.getIp(req)); | |
52 | + lgnHstryVO.setCntnOperSys(httpRequestUtil.getOS(httpRequestUtil.getUserAgent(req))); | |
53 | + lgnHstryVO.setDeviceNm(httpRequestUtil.getDevice(httpRequestUtil.getUserAgent(req))); | |
54 | + lgnHstryVO.setBrwsrNm(httpRequestUtil.getBrowser(httpRequestUtil.getUserAgent(req))); | |
55 | + lgnHstryService.LgnHstrySave(lgnHstryVO); | |
56 | + | |
57 | + // 로그인 방식 확인 JWT or SESSION | |
58 | + String loginType = loginModeService.getLoginMode(); | |
59 | + | |
60 | + // 토큰 생성(access, refresh) | |
61 | + String accessToken = jwtUtil.createJwt("Authorization", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_ACCESSTIME); | |
62 | + String refreshToken = jwtUtil.createJwt("refresh", mber.getMbrId(), mber.getLgnId(), mber.getMbrNm(), (List) mber.getAuthorities(), JWT_REFRESHTIME); | |
63 | + | |
64 | + // refreshToken이 현재 IP와 계정으로 등록되어 있는지 확인 | |
65 | + RefreshTknVO refresh = new RefreshTknVO(); | |
66 | + refresh.setMbrId(mber.getMbrId()); | |
67 | + | |
68 | + // refresh 토큰이 현재 아이피와 아이디로 DB에 등록 되어 있다면 | |
69 | + if (refreshTokenService.findByCheckRefresh(req, refresh)) { | |
70 | + refreshTokenService.delete(req, refresh); | |
71 | + } | |
72 | + // refreshToken DB 저장 | |
73 | + refresh.setToken(refreshToken); | |
74 | + | |
75 | + if ("S".equals(loginType)) { | |
76 | + HttpSession session = req.getSession(true); | |
77 | + session.setAttribute("JWT_TOKEN", accessToken); | |
78 | + | |
79 | + // 중복 로그인 비허용일 때 기존 세션 만료 | |
80 | + if (!loginPolicyService.getPolicy()) { | |
81 | + sessionUtil.registerSession(mber.getMbrId(), session); | |
82 | + } | |
83 | + Map<String, Object> result = new HashMap<>(); | |
84 | + result.put("mbrId", mber.getMbrId()); | |
85 | + result.put("mbrNm", mber.getMbrNm()); | |
86 | + result.put("roles", mber.getAuthorList()); | |
87 | + | |
88 | + res.setContentType("application/json;charset=UTF-8"); | |
89 | + res.setStatus(HttpStatus.OK.value()); | |
90 | + new ObjectMapper().writeValue(res.getOutputStream(), result); | |
91 | + } else { | |
92 | + res.setHeader("Authorization", accessToken); | |
93 | + res.addCookie(jwtUtil.createCookie("refresh", refreshToken, COOKIE_TIME)); | |
94 | + | |
95 | + // 중복 로그인 비허용일 때 Redis 저장 | |
96 | + if (!loginPolicyService.getPolicy()) { | |
97 | + redisTemplate.delete("jwt:" + mber.getMbrId()); | |
98 | + redisTemplate.opsForValue().set("jwt:" + mber.getMbrId(), accessToken, JWT_ACCESSTIME, TimeUnit.MILLISECONDS); | |
99 | + } | |
100 | + } | |
101 | + | |
102 | + refreshTokenService.saveRefreshToken(req, res, refresh, JWT_REFRESHTIME); | |
103 | + res.setHeader("login-type", loginType); | |
104 | + } | |
105 | + catch (IOException ioe) { | |
106 | + throw new RuntimeException(ioe); | |
107 | + } | |
108 | + catch (Exception e) { | |
109 | + throw e; | |
110 | + } | |
111 | + } | |
112 | +} |
--- src/main/java/com/takensoft/common/verify/service/Impl/EmailServiceImpl.java
+++ src/main/java/com/takensoft/common/verify/service/Impl/EmailServiceImpl.java
... | ... | @@ -41,8 +41,6 @@ |
41 | 41 |
private final EmailDAO emailDAO; |
42 | 42 |
private final JWTUtil jwtUtil; |
43 | 43 |
private final JavaMailSender mailSender; |
44 |
-// @Autowired |
|
45 |
-// @Qualifier("redisTemplateObject") |
|
46 | 44 |
private final RedisTemplate<String, Object> redisTemplate; |
47 | 45 |
|
48 | 46 |
@Value("${spring.mail.verifyTime}") |
--- src/main/java/com/takensoft/common/verify/vo/EmailVO.java
+++ src/main/java/com/takensoft/common/verify/vo/EmailVO.java
... | ... | @@ -15,9 +15,12 @@ |
15 | 15 |
*/ |
16 | 16 |
@Setter |
17 | 17 |
@Getter |
18 |
+@ToString |
|
19 |
+@Builder |
|
18 | 20 |
@NoArgsConstructor |
19 | 21 |
@AllArgsConstructor |
20 | 22 |
public class EmailVO { |
23 |
+ private String mbrId; // 회원아이디 |
|
21 | 24 |
private String email; // 이메일 |
22 | 25 |
private String code; // 인증코드 |
23 | 26 |
private long createdAt; // 인증코드 생성일시 |
--- src/main/java/com/takensoft/common/verify/web/EmailController.java
+++ src/main/java/com/takensoft/common/verify/web/EmailController.java
... | ... | @@ -1,22 +1,39 @@ |
1 | 1 |
package com.takensoft.common.verify.web; |
2 | 2 |
|
3 |
+import com.fasterxml.jackson.databind.ObjectMapper; |
|
4 |
+import com.takensoft.cms.loginPolicy.service.LoginModeService; |
|
5 |
+import com.takensoft.cms.loginPolicy.service.LoginPolicyService; |
|
6 |
+import com.takensoft.cms.mber.service.LgnHstryService; |
|
7 |
+import com.takensoft.cms.mber.service.MberService; |
|
8 |
+import com.takensoft.cms.mber.vo.LgnHstryVO; |
|
9 |
+import com.takensoft.cms.mber.vo.MberVO; |
|
10 |
+import com.takensoft.cms.token.service.RefreshTokenService; |
|
11 |
+import com.takensoft.cms.token.vo.RefreshTknVO; |
|
3 | 12 |
import com.takensoft.common.message.MessageCode; |
4 |
-import com.takensoft.common.util.ResponseUtil; |
|
13 |
+import com.takensoft.common.util.*; |
|
5 | 14 |
import com.takensoft.common.verify.service.EmailService; |
6 | 15 |
import com.takensoft.common.verify.vo.EmailVO; |
16 |
+import jakarta.servlet.http.HttpServletRequest; |
|
7 | 17 |
import jakarta.servlet.http.HttpServletResponse; |
18 |
+import jakarta.servlet.http.HttpSession; |
|
8 | 19 |
import lombok.RequiredArgsConstructor; |
9 | 20 |
import lombok.extern.slf4j.Slf4j; |
21 |
+import org.springframework.beans.factory.annotation.Value; |
|
22 |
+import org.springframework.data.redis.core.RedisTemplate; |
|
23 |
+import org.springframework.http.HttpStatus; |
|
10 | 24 |
import org.springframework.http.ResponseEntity; |
11 | 25 |
import org.springframework.web.bind.annotation.*; |
12 | 26 |
import org.springframework.web.multipart.MultipartFile; |
13 | 27 |
|
14 | 28 |
import java.io.File; |
15 | 29 |
import java.io.FileInputStream; |
30 |
+import java.io.IOException; |
|
16 | 31 |
import java.io.OutputStream; |
17 | 32 |
import java.net.URLEncoder; |
18 | 33 |
import java.util.HashMap; |
34 |
+import java.util.List; |
|
19 | 35 |
import java.util.Map; |
36 |
+import java.util.concurrent.TimeUnit; |
|
20 | 37 |
|
21 | 38 |
/** |
22 | 39 |
* @author 하석형 |
... | ... | @@ -35,6 +52,23 @@ |
35 | 52 |
|
36 | 53 |
private final EmailService emailService; |
37 | 54 |
private final ResponseUtil resUtil; |
55 |
+ private final MberService mberService; |
|
56 |
+ private final HttpRequestUtil httpRequestUtil; |
|
57 |
+ private final LgnHstryService lgnHstryService; |
|
58 |
+ private final LoginModeService loginModeService; |
|
59 |
+ private final RefreshTokenService refreshTokenService; |
|
60 |
+ private final LoginPolicyService loginPolicyService; |
|
61 |
+ private final JWTUtil jwtUtil; |
|
62 |
+ private final SessionUtil sessionUtil; |
|
63 |
+ private final RedisTemplate<String, String> redisTemplate; |
|
64 |
+ private final LoginUtil loginUtil; |
|
65 |
+ |
|
66 |
+ @Value("${jwt.accessTime}") |
|
67 |
+ private long JWT_ACCESSTIME; |
|
68 |
+ @Value("${jwt.refreshTime}") |
|
69 |
+ private long JWT_REFRESHTIME; |
|
70 |
+ @Value("${cookie.time}") |
|
71 |
+ private int COOKIE_TIME; // 쿠키 유지 시간 |
|
38 | 72 |
|
39 | 73 |
/** |
40 | 74 |
* @param emailVO - 이메일 정보 |
... | ... | @@ -47,7 +81,7 @@ |
47 | 81 |
|
48 | 82 |
boolean result = emailService.sendEmailVerifyCode(emailVO); |
49 | 83 |
|
50 |
- return resUtil.successRes(result, MessageCode.COMMON_SUCCESS); |
|
84 |
+ return resUtil.successRes(result, MessageCode.EMAIL_SEND_SUCCESS); |
|
51 | 85 |
} |
52 | 86 |
|
53 | 87 |
/** |
... | ... | @@ -63,4 +97,33 @@ |
63 | 97 |
|
64 | 98 |
return resUtil.successRes(result, MessageCode.COMMON_SUCCESS); |
65 | 99 |
} |
100 |
+ |
|
101 |
+ /** |
|
102 |
+ * @param emailVO - 이메일 정보 |
|
103 |
+ * @return ResponseEntity - 이메일 인증코드 확인 응답 결과 |
|
104 |
+ * |
|
105 |
+ * 2차 인증 이메일 인증코드 확인 |
|
106 |
+ */ |
|
107 |
+ @PostMapping("/check2ndAuthEmailVerifyCode.json") |
|
108 |
+ public void check2ndAuthEmailVerifyCode(@RequestBody EmailVO emailVO, HttpServletRequest req, HttpServletResponse res) throws IOException { |
|
109 |
+ |
|
110 |
+ boolean authResult = emailService.checkEmailVerifyCode(emailVO); // 이메일 인증코드 확인 |
|
111 |
+ if(authResult) { |
|
112 |
+ HashMap<String, Object> findMber = new HashMap<>(); |
|
113 |
+ findMber.put("mbrId", emailVO.getMbrId()); |
|
114 |
+ MberVO mber = mberService.findByMbr(findMber); |
|
115 |
+ |
|
116 |
+ loginUtil.successLogin(mber, req, res); |
|
117 |
+ } else { |
|
118 |
+ // 인증 실패 시 예외 처리 |
|
119 |
+ Map<String, Object> result = new HashMap<>(); |
|
120 |
+ res.setContentType("application/json;charset=UTF-8"); |
|
121 |
+ res.setStatus(HttpStatus.UNAUTHORIZED.value()); |
|
122 |
+ result.put("message", "인증에 실패했습니다. 올바른 인증코드를 입력해주세요."); |
|
123 |
+ new ObjectMapper().writeValue(res.getOutputStream(), result); |
|
124 |
+ return; |
|
125 |
+ } |
|
126 |
+ |
|
127 |
+// return resUtil.successRes(authResult, MessageCode.COMMON_SUCCESS); |
|
128 |
+ } |
|
66 | 129 |
} |
--- src/main/resources/message/messages_en.yml
+++ src/main/resources/message/messages_en.yml
... | ... | @@ -61,6 +61,7 @@ |
61 | 61 |
|
62 | 62 |
# 이메일 인증 관련 |
63 | 63 |
email: |
64 |
+ send_success: "Email sent successfully." |
|
64 | 65 |
send_fail: "Failed to send email." |
65 | 66 |
verify_success: "Email verification completed successfully." |
66 | 67 |
verify_expired: "Email verification has expired." |
--- src/main/resources/message/messages_ko.yml
+++ src/main/resources/message/messages_ko.yml
... | ... | @@ -62,6 +62,7 @@ |
62 | 62 |
|
63 | 63 |
# 이메일 인증 관련 |
64 | 64 |
email: |
65 |
+ send_success: "이메일을 발송했습니다." |
|
65 | 66 |
send_fail: "이메일 발송에 실패했습니다." |
66 | 67 |
verify_success: "이메일 인증이 완료되었습니다." |
67 | 68 |
verify_expired: "인증 시간이 만료되었습니다." |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?