
250527 하석형 관리자 페이지 로그인 -> 관리자계정 로그인 시 2차 인증 로직으로 변경
@e383166f1ecd4c6357971feb0a12017494dd496a
--- src/main/java/com/takensoft/common/config/SecurityConfig.java
+++ src/main/java/com/takensoft/common/config/SecurityConfig.java
... | ... | @@ -4,15 +4,12 @@ |
4 | 4 |
import com.takensoft.cms.cntxtPth.service.CntxtPthService; |
5 | 5 |
import com.takensoft.cms.loginPolicy.service.LoginModeService; |
6 | 6 |
import com.takensoft.cms.loginPolicy.service.LoginPolicyService; |
7 |
-import com.takensoft.cms.mber.service.LgnHstryService; |
|
8 |
-import com.takensoft.cms.token.service.RefreshTokenService; |
|
9 | 7 |
import com.takensoft.common.filter.*; |
10 | 8 |
import com.takensoft.common.util.HttpRequestUtil; |
11 | 9 |
import com.takensoft.common.exception.CustomAccessDenieHandler; |
12 | 10 |
import com.takensoft.common.exception.CustomAuthenticationEntryPoint; |
13 | 11 |
import com.takensoft.common.util.JWTUtil; |
14 | 12 |
import com.takensoft.common.util.LoginUtil; |
15 |
-import com.takensoft.common.util.SessionUtil; |
|
16 | 13 |
import com.takensoft.common.verify.service.Impl.EmailServiceImpl; |
17 | 14 |
import com.takensoft.common.oauth.service.Impl.CustomOAuth2UserServiceImpl; |
18 | 15 |
import com.takensoft.common.oauth.handler.OAuth2AuthenticationSuccessHandler; |
... | ... | @@ -28,7 +25,6 @@ |
28 | 25 |
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
29 | 26 |
import org.springframework.security.config.http.SessionCreationPolicy; |
30 | 27 |
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
31 |
-import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; |
|
32 | 28 |
import org.springframework.security.web.SecurityFilterChain; |
33 | 29 |
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
34 | 30 |
import org.springframework.security.web.context.SecurityContextPersistenceFilter; |
... | ... | @@ -56,8 +52,6 @@ |
56 | 52 |
// AuthenticationManager가 인자로 받을 AuthenticationConfiguration 객체 생성자 주입 |
57 | 53 |
private final AuthenticationConfiguration authenticationConfiguration; |
58 | 54 |
private final JWTUtil jwtUtil; |
59 |
- private final RefreshTokenService refreshTokenService; |
|
60 |
- private final LgnHstryService lgnHstryService; |
|
61 | 55 |
private final CntxtPthService cntxtPthService; |
62 | 56 |
private final AccesCtrlService accesCtrlService; |
63 | 57 |
private final CustomAuthenticationEntryPoint authenticationEntryPoint; |
... | ... | @@ -67,7 +61,6 @@ |
67 | 61 |
private final LoginModeService loginModeService; |
68 | 62 |
private final LoginPolicyService loginPolicyService; |
69 | 63 |
private final EmailServiceImpl emailServiceImpl; |
70 |
- private final SessionUtil sessionUtil; |
|
71 | 64 |
private final LoginUtil loginUtil; |
72 | 65 |
|
73 | 66 |
@Autowired |
... | ... | @@ -80,22 +73,15 @@ |
80 | 73 |
private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler; |
81 | 74 |
|
82 | 75 |
private static String FRONT_URL; // 프론트 접근 허용 URL |
83 |
- private static long JWT_ACCESSTIME; // access 토큰 유지 시간 |
|
84 |
- private static long JWT_REFRESHTIME; // refresh 토큰 유지 시간 |
|
85 |
- private static int COOKIE_TIME; // 쿠키 유지 시간 |
|
86 | 76 |
|
87 | 77 |
private final RedisTemplate<String, String> redisTemplate; |
88 | 78 |
|
89 | 79 |
/** |
90 | 80 |
* SecurityConfig 생성자 |
91 | 81 |
*/ |
92 |
- public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil, RefreshTokenService refreshTokenService, CntxtPthService cntxtPthService, AccesCtrlService accesCtrlService, AppConfig appConfig, |
|
93 |
- LgnHstryService lgnHstryService, CustomAuthenticationEntryPoint authenticationEntryPoint, CustomAccessDenieHandler accessDenieHandler, HttpRequestUtil httpRequestUtil, |
|
94 |
- 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, |
|
95 |
- LoginUtil loginUtil) { |
|
82 |
+ public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTUtil jwtUtil, CntxtPthService cntxtPthService, AccesCtrlService accesCtrlService, AppConfig appConfig, CustomAuthenticationEntryPoint authenticationEntryPoint, CustomAccessDenieHandler accessDenieHandler, |
|
83 |
+ HttpRequestUtil httpRequestUtil, LoginModeService loginModeService, LoginPolicyService loginPolicyService, EmailServiceImpl emailServiceImpl, @Value("${front.url}") String fUrl, RedisTemplate<String, String> redisTemplate, LoginUtil loginUtil) { |
|
96 | 84 |
this.authenticationConfiguration = authenticationConfiguration; |
97 |
- this.refreshTokenService = refreshTokenService; |
|
98 |
- this.lgnHstryService = lgnHstryService; |
|
99 | 85 |
this.cntxtPthService = cntxtPthService; |
100 | 86 |
this.accesCtrlService = accesCtrlService; |
101 | 87 |
this.authenticationEntryPoint = authenticationEntryPoint; |
... | ... | @@ -106,11 +92,7 @@ |
106 | 92 |
this.loginModeService = loginModeService; |
107 | 93 |
this.loginPolicyService = loginPolicyService; |
108 | 94 |
this.emailServiceImpl = emailServiceImpl; |
109 |
- this.sessionUtil = sessionUtil; |
|
110 | 95 |
this.FRONT_URL = fUrl; |
111 |
- this.JWT_ACCESSTIME = aTime; |
|
112 |
- this.JWT_REFRESHTIME = rTime; |
|
113 |
- this.COOKIE_TIME = ctime; |
|
114 | 96 |
this.redisTemplate = redisTemplate; |
115 | 97 |
this.loginUtil = loginUtil; |
116 | 98 |
} |
... | ... | @@ -207,9 +189,7 @@ |
207 | 189 |
http.addFilterBefore(new AccesFilter(accesCtrlService, httpRequestUtil, appConfig), JWTFilter.class); |
208 | 190 |
|
209 | 191 |
// 로그인 필터 |
210 |
- http.addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil, refreshTokenService, lgnHstryService, httpRequestUtil, |
|
211 |
- loginModeService, loginPolicyService, emailServiceImpl, sessionUtil, JWT_ACCESSTIME, JWT_REFRESHTIME, COOKIE_TIME, redisTemplate, |
|
212 |
- loginUtil), UsernamePasswordAuthenticationFilter.class); |
|
192 |
+ http.addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), emailServiceImpl, loginUtil), UsernamePasswordAuthenticationFilter.class); |
|
213 | 193 |
|
214 | 194 |
|
215 | 195 |
return http.build(); |
--- src/main/java/com/takensoft/common/filter/LoginFilter.java
+++ src/main/java/com/takensoft/common/filter/LoginFilter.java
... | ... | @@ -1,25 +1,13 @@ |
1 | 1 |
package com.takensoft.common.filter; |
2 | 2 |
|
3 | 3 |
import com.fasterxml.jackson.databind.ObjectMapper; |
4 |
-import com.takensoft.cms.loginPolicy.service.LoginModeService; |
|
5 |
-import com.takensoft.cms.loginPolicy.service.LoginPolicyService; |
|
6 | 4 |
import com.takensoft.cms.mber.dto.LoginDTO; |
7 |
-import com.takensoft.cms.mber.service.LgnHstryService; |
|
8 |
-import com.takensoft.cms.token.service.RefreshTokenService; |
|
9 |
-import com.takensoft.cms.mber.vo.LgnHstryVO; |
|
10 | 5 |
import com.takensoft.cms.mber.vo.MberVO; |
11 |
-import com.takensoft.cms.token.vo.RefreshTknVO; |
|
12 | 6 |
import com.takensoft.common.exception.FilterExceptionHandler; |
13 |
-import com.takensoft.common.util.HttpRequestUtil; |
|
14 |
-import com.takensoft.common.util.JWTUtil; |
|
15 | 7 |
import com.takensoft.common.util.LoginUtil; |
16 |
-import com.takensoft.common.util.SessionUtil; |
|
17 | 8 |
import com.takensoft.common.verify.service.Impl.EmailServiceImpl; |
18 | 9 |
import com.takensoft.common.verify.vo.EmailVO; |
19 |
-import jakarta.servlet.http.HttpSession; |
|
20 | 10 |
import lombok.SneakyThrows; |
21 |
-import org.springframework.beans.factory.annotation.Value; |
|
22 |
-import org.springframework.data.redis.core.RedisTemplate; |
|
23 | 11 |
import org.springframework.http.HttpStatus; |
24 | 12 |
import org.springframework.security.authentication.AuthenticationManager; |
25 | 13 |
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
... | ... | @@ -34,9 +22,7 @@ |
34 | 22 |
import jakarta.servlet.http.HttpServletResponse; |
35 | 23 |
import java.io.IOException; |
36 | 24 |
import java.util.HashMap; |
37 |
-import java.util.List; |
|
38 | 25 |
import java.util.Map; |
39 |
-import java.util.concurrent.TimeUnit; |
|
40 | 26 |
|
41 | 27 |
/** |
42 | 28 |
* @author takensoft |
... | ... | @@ -52,46 +38,14 @@ |
52 | 38 |
public class LoginFilter extends UsernamePasswordAuthenticationFilter { |
53 | 39 |
|
54 | 40 |
private final AuthenticationManager authenticationManager; |
55 |
- private final JWTUtil jwtUtil; |
|
56 |
- private final RefreshTokenService refreshTokenService; |
|
57 |
- private final LgnHstryService lgnHstryService; |
|
58 |
- private final HttpRequestUtil httpRequestUtil; |
|
59 |
- private final LoginModeService loginModeService; |
|
60 |
- private final LoginPolicyService loginPolicyService; |
|
61 | 41 |
private final EmailServiceImpl emailServiceImpl; |
62 |
- private final SessionUtil sessionUtil; |
|
63 | 42 |
private final LoginUtil loginUtil; |
64 |
- |
|
65 |
- private static long JWT_ACCESSTIME; // access 토큰 유지 시간 |
|
66 |
- private static long JWT_REFRESHTIME; // refresh 토큰 유지 시간 |
|
67 |
- private static int COOKIE_TIME; // 쿠키 유지 시간 |
|
68 |
- |
|
69 |
- private final RedisTemplate<String, String> redisTemplate; |
|
70 | 43 |
/** |
71 |
- * @param aTime - 액세스 토큰의 유효 시간 (application.yml에서 값을 읽어 옴) |
|
72 |
- * @param rTime - 리프레시 토큰의 유효 시간 (application.yml에서 값을 읽어 옴) |
|
73 |
- * @param ctime - 쿠키의 유효 시간 (application.yml에서 값을 읽어 옴) |
|
74 |
- * @param authenticationManager - 인증 관리자 |
|
75 |
- * @param jwtUtil - JWT 유틸리티 |
|
76 |
- * |
|
77 | 44 |
* LoginFilter 생성자 |
78 | 45 |
*/ |
79 |
- public LoginFilter(AuthenticationManager authenticationManager, JWTUtil jwtUtil, RefreshTokenService refreshTokenService, LgnHstryService lgnHstryService, HttpRequestUtil httpRequestUtil, |
|
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) { |
|
46 |
+ public LoginFilter(AuthenticationManager authenticationManager, EmailServiceImpl emailServiceImpl, LoginUtil loginUtil) { |
|
82 | 47 |
this.authenticationManager = authenticationManager; |
83 |
- this.jwtUtil = jwtUtil; |
|
84 |
- this.refreshTokenService = refreshTokenService; |
|
85 |
- this.lgnHstryService = lgnHstryService; |
|
86 |
- this.httpRequestUtil = httpRequestUtil; |
|
87 |
- this.loginModeService = loginModeService; |
|
88 |
- this.loginPolicyService = loginPolicyService; |
|
89 | 48 |
this.emailServiceImpl = emailServiceImpl; |
90 |
- this.sessionUtil = sessionUtil; |
|
91 |
- this.JWT_ACCESSTIME = aTime; |
|
92 |
- this.JWT_REFRESHTIME = rTime; |
|
93 |
- this.COOKIE_TIME = ctime; |
|
94 |
- this.redisTemplate = redisTemplate; |
|
95 | 49 |
this.loginUtil = loginUtil; |
96 | 50 |
|
97 | 51 |
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/mbr/loginProc.json","POST")); |
... | ... | @@ -138,98 +92,36 @@ |
138 | 92 |
Map<String, Object> result = new HashMap<>(); |
139 | 93 |
|
140 | 94 |
MberVO mber = (MberVO) authentication.getPrincipal(); |
95 |
+ boolean isAdmin = mber.getAuthorities().stream().anyMatch(role -> role.getAuthority().equals("ROLE_ADMIN")); // 관리자 권한 여부 |
|
96 |
+ String lgnReqPage = (String) req.getAttribute("lgnReqPage"); // 로그인 요청 페이지 정보 (A: 관리자, U: 사용자) |
|
141 | 97 |
|
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()); |
|
98 |
+ // 관리자일 경우 2차 인증(이메일 인증) 코드 발송 |
|
99 |
+ if(isAdmin) { |
|
100 |
+ EmailVO emailVO = new EmailVO().builder() |
|
101 |
+ .email(mber.getEml()) |
|
102 |
+ .build(); |
|
103 |
+ emailServiceImpl.sendEmailVerifyCode(emailVO); |
|
104 |
+ res.setContentType("application/json;charset=UTF-8"); |
|
105 |
+ res.setStatus(HttpStatus.OK.value()); |
|
106 |
+ result.put("mbrId", mber.getMbrId()); |
|
107 |
+ result.put("email", mber.getEml()); |
|
155 | 108 |
|
156 |
- res.setContentType("application/json;charset=UTF-8"); |
|
157 |
- res.setStatus(HttpStatus.OK.value()); |
|
109 |
+ res.setContentType("application/json;charset=UTF-8"); |
|
110 |
+ res.setStatus(HttpStatus.OK.value()); |
|
158 | 111 |
|
159 |
- new ObjectMapper().writeValue(res.getOutputStream(), result); |
|
160 |
- } else { |
|
161 |
- // 관리자 권한이 없는 경우 접근 권한이 없습니다 |
|
112 |
+ new ObjectMapper().writeValue(res.getOutputStream(), result); |
|
113 |
+ // 사용자일 경우 |
|
114 |
+ } else { |
|
115 |
+ // 사용자가 관리자 로그인 페이지로 접근할 경우 |
|
116 |
+ if("A".equals(lgnReqPage)) { |
|
162 | 117 |
res.setContentType("application/json;charset=UTF-8"); |
163 | 118 |
res.setStatus(HttpStatus.FORBIDDEN.value()); |
164 | 119 |
|
165 | 120 |
result.put("message", "접근 권한이 없습니다."); |
166 | 121 |
new ObjectMapper().writeValue(res.getOutputStream(), result); |
122 |
+ } else { |
|
123 |
+ loginUtil.successLogin(mber, req, res); // 로그인 성공 처리 |
|
167 | 124 |
} |
168 |
- } else { |
|
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); |
|
233 | 125 |
} |
234 | 126 |
} |
235 | 127 |
|
--- src/main/java/com/takensoft/common/util/LoginUtil.java
+++ src/main/java/com/takensoft/common/util/LoginUtil.java
... | ... | @@ -36,11 +36,11 @@ |
36 | 36 |
private final RedisTemplate<String, String> redisTemplate; |
37 | 37 |
|
38 | 38 |
@Value("${jwt.accessTime}") |
39 |
- private long JWT_ACCESSTIME; |
|
39 |
+ private long JWT_ACCESSTIME; // access 토큰 유지 시간 |
|
40 | 40 |
@Value("${jwt.refreshTime}") |
41 |
- private long JWT_REFRESHTIME; |
|
41 |
+ private long JWT_REFRESHTIME; // refresh 토큰 유지 시간 |
|
42 | 42 |
@Value("${cookie.time}") |
43 |
- private int COOKIE_TIME; |
|
43 |
+ private int COOKIE_TIME; // 쿠키 유지 시간 |
|
44 | 44 |
|
45 | 45 |
public void successLogin(MberVO mber, HttpServletRequest req, HttpServletResponse res) { |
46 | 46 |
try { |
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?