Spring Security, Spring Cloud, JWT, MSA
JWT + Spring Security + Spring Cloud = MSA 1. ํ๊ฒฝ์ธํ
์ ์ด์ด์ Spring Security๋ฅผ ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฌ์ฉํด๋ณด์
- ์ฐธ๊ณ ๋ก JWT + Spring Security + Spring Cloud = MSA 1. ํ๊ฒฝ์ธํ
์์ ๋ฑ๋กํ discovery์์
user-service
ํ๋ก์ ํธ์ด๋ค
Spring Security์ ๋ํด ๊ธฐ๋ณธ์ ์ธ ๊ฒ์ ์๋ค๋ ๊ฐ์ ํ์ ์งํํ์๋ค. Spring Security์ ๋ํ ์์ธํ ์ค๋ช ์ Spring Security๋ฅผ ์ด์ฉํ ๋ก๊ทธ์ธ ์ฒ๋ฆฌ์์ ์์ธํ๊ฒ ์ค๋ช ํ์๋ค
Spring Security๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ธ์ ๊ณต์ ๋ฅผ ์ ์ ๋ก ๋ก๊ทธ์ธ ์ฒ๋ฆฌํ๋ค. ํ์ง๋ง MSA ๋ฐฉ์์์ ์ธ์ ๊ณต์ ๊ฐ ๊น๋ค๋กญ๊ธฐ๋๋ฌธ์ jwt ํ ํฐ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ์๋ค. ์ด๋ฅผ ์ํด Spring Security๋ฅผ ์ ๋ถ๋ค ์ปค์คํ ์งํ
Security ํญ๋ชฉ
์ ์ฒด์ ์ธ ๋ก๊ทธ์ธ ๊ฒ์ฆ ํํฐ : AuthenticationFilter
์ฑ๊ณต ์คํจ ํ๋จ: CustomAuthenticationProvider
์ฑ๊ณต์ ์ฒ๋ฆฌ: AuthenticationFilter.successfulAuthentication
์คํจ์ ์ฒ๋ฆฌ: AuthFailureHandler
1. WebSecurity
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurity extends WebSecurityConfigurerAdapter {
private final UserService userService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final Environment env;
private final JwtTokenProvider jwtTokenProvider;
private final CustomAuthenticationProvider authProvider;
private final AuthFailureHandler authFailureHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/**")
.hasIpAddress("127.0.0.1") //127.0.0.1์์ ์ ์ํ๋ ๋ชจ๋ ์๋น์ค์์ฒญ์ ๊ถํ์์ด ์ฌ์ฉ ๊ฐ๋ฅํ๋ค
.antMatchers("/css/**").permitAll()
.and()
.addFilter(getAuthenticationFilter()); // Spring Security์์ ์ ๊ณตํ๋ ๋ก๊ทธ์ธ ์ธ์ฆ ํด์ ์ฌ์ฉ์ํ๊ณ ์ง์ ์ธ์ฆ ํํฐ๋ฅผ ๋ง๋ ๋ค
http.headers().frameOptions().disable(); // for H2 frame
}
private AuthenticationFilter getAuthenticationFilter() throws Exception {
AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManager(), userService, env, jwtTokenProvider);
authenticationFilter.setFailureHandler(authFailureHandler); //๋ก๊ทธ์ธ ์คํจ ํธ๋ค๋ฌ ์ฃผ์
return authenticationFilter;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder);
}
}
JwtTokenProvider
๋ Jwt๊ด๋ จ์ ํธ์ด๋ค. ์๋์ ์ค๋ช
์ถ๊ฐ
์ฒซ๋ฒ์งธ configure
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/**")
.hasIpAddress("127.0.0.1") //127.0.0.1์์ ์ ์ํ๋ ๋ชจ๋ ์๋น์ค์์ฒญ์ ๊ถํ์์ด ์ฌ์ฉ ๊ฐ๋ฅํ๋ค
.antMatchers("/css/**").permitAll()
.and()
.addFilter(getAuthenticationFilter()); // Spring Security์์ ์ ๊ณตํ๋ ๋ก๊ทธ์ธ ์ธ์ฆ ํด์ ์ฌ์ฉ์ํ๊ณ ์ง์ ์ธ์ฆ ํํฐ๋ฅผ ๋ง๋ ๋ค
http.headers().frameOptions().disable(); // for H2 frame
}
private AuthenticationFilter getAuthenticationFilter() throws Exception {
AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManager(), userService, env, jwtTokenProvider);
authenticationFilter.setFailureHandler(authFailureHandler); //๋ก๊ทธ์ธ ์คํจ ํธ๋ค๋ฌ ์ฃผ์
return authenticationFilter;
}
addFilter(getAuthenticationFilter());
๋ฅผ ํตํดAuthenticationFilter
๋ฅผ ์ฌ์ฉํ๋ค๊ณ ๋ช ์ํ๋ค. ์ฆ, Spring Security์์ ์ ๊ณตํ๋ ๋ก๊ทธ์ธ ํํฐ๋ฅผ ์ฌ์ฉ์ํ๊ณ ์ง์ ์ธ์ฆ ํํฐ๋ง๋ค์ด ์ฌ์ฉํ๋ค. ์ด ํํฐ๋CustomAuthenticationProvider
์๊ฒ ๋ก๊ทธ์ธ์ ์๋ํ๋ผ๊ณ ๋ช ๋ น์ ๋ด๋ฆฌ๊ณ ๋ก๊ทธ์ธ๊ฒ์ฆ์์ ์ ๋ฌ๋ ๊ฒฐ๊ณผ(์ฑ๊ณตor์คํจ)์ ๋ฐ๋ผ ๋ก์ง์ ์คํํ๋ค.
๋๋ฒ์งธ configure
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder);
}
CustomAuthenticationProvider
๋ฅผ ์ฃผ์ ํ๋ค. ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ํผ์ ์ ๋ ฅํ ์CustomAuthenticationProvider
๋ฅผ ํตํด ๋ก๊ทธ์ธ ์ฑ๊ณต์ด๋ ์คํจ๋ฅผ ํ๋จํ๋ค.
2. JWT
- jwt ๊ด๋ จ ์ ํธํจ์
- application.yaml์์ ์ง์ ํ ๊ฐ๋ค์
@Value
ํตํด ์ฌ์ฉํ๋ค
@Component
@Slf4j
public class JwtTokenProvider {
@Value("${token.access-expired-time}")
private long ACCESS_EXPIRED_TIME;
@Value("${token.refresh-expired-time}")
private long REFRESH_EXPIRED_TIME;
@Value("${token.secret}")
private String SECRET;
public String getUserId(String token) {
return getClaimsFromJwtToken(token).getSubject();
}
public String getRefreshTokenId(String token) {
return getClaimsFromJwtToken(token).get("value").toString();
}
public List<String> getRoles(String token) {
return (List<String>) getClaimsFromJwtToken(token).get("roles");
}
public void validateJwtToken(String token) {
try {
Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
} catch (SignatureException | MalformedJwtException |
UnsupportedJwtException | IllegalArgumentException | ExpiredJwtException jwtException) {
throw jwtException;
}
}
private Claims getClaimsFromJwtToken(String token) {
try {
return Jwts.parser().setSigningKey(SECRET)
.parseClaimsJws(token).getBody();
} catch (ExpiredJwtException e) {
return e.getClaims();
}
}
public Date getExpiredTime(String token) {
return getClaimsFromJwtToken(token).getExpiration();
}
public String createJwtAccessToken(String userId, String uri, UserRole role) {
Claims claims = Jwts.claims();
claims.put("role", role);
return Jwts.builder()
.setClaims(claims)
.setSubject(userId)
.setExpiration(
new Date(System.currentTimeMillis() + ACCESS_EXPIRED_TIME)
)
.setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS512, SECRET)
.setIssuer(uri)
.compact();
}
public String createJwtRefreshToken() {
Claims claims = Jwts.claims();
claims.put("value", UUID.randomUUID());
return Jwts.builder()
.addClaims(claims)
.setExpiration(
new Date(System.currentTimeMillis() + REFRESH_EXPIRED_TIME)
)
.setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
}
3. ํํฐ ๊ตฌํ
/**
* ๋ก๊ทธ์ธ ์ฒ๋ฆฌ ํํฐ
* @author ๊น์ฐฌ์
*/
@Slf4j
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private UserService userService;
private Environment env;
private final JwtTokenProvider jwtTokenProvider;
@Autowired
public AuthenticationFilter(AuthenticationManager authenticationManager,
UserService userService,
Environment env, JwtTokenProvider jwtTokenProvider){
this.jwtTokenProvider = jwtTokenProvider;
this.userService = userService;
this.env = env;
super.setAuthenticationManager(authenticationManager);
}
/**
* ์ธ์ฆ ์๋
* <p>์
๋ ฅ๋ฐ์ ๊ฐ์ ์ธ์ฆ ํ ํฐ์ ์ ์ฅ
* <p>์ดํ {@link CustomAuthenticationProvider#authenticate(Authentication)}๋ก ์ ๋ฌํ๋ค
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try{
RequestLogin creds = new ObjectMapper().readValue(request.getInputStream(), RequestLogin.class);
if (creds==null){
throw new NoActivatedException("hello");
}
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
creds.getEmail(),
creds.getPassword(),
new ArrayList<>()
)
);
} catch(IOException e) {
throw new RuntimeException(e);
}
}
/**
* ๋ก๊ทธ์ธ ์ฑ๊ณต์ ์ฒ๋ฆฌ
* <p> JWT ํ ํฐ์ ๋ฐํํ๊ณ ์ฟ ํค์ ํ ํฐ ๊ฐ์ ์ ์ฅํ๋ค
*/
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult)
throws IOException, ServletException {
String userName = ((User)authResult.getPrincipal()).getUsername();
UserDto userDetails = userService.getUserDetailsByEmail(userName);
String token = jwtTokenProvider.createJwtAccessToken(
userDetails.getId(),
request.getRequestURI(),
userDetails.getRole()
);
ResponseCookie cookie = ResponseCookie.from("token", token)
.sameSite("Strict")
.path("/")
.build();
response.addHeader("Set-Cookie", cookie.toString() + ";HttpOnly");
response.addHeader("token", token);
}
/**
* ์คํจ ํธ๋ค๋ฌ({@link AuthFailureHandler})๋ฅผ ์ง์ ์ฃผ์ํ๋ค
*/
public void setFailureHandler(AuthenticationFailureHandler failureHandler) {
Assert.notNull(failureHandler, "FailureHandler๊ฐ ์์ต๋๋ค");
super.setAuthenticationFailureHandler(failureHandler);
}
}
attemptAuthentication
: ๋ก๊ทธ์ธ๊ฒ์ฆ์ฒ๋ฆฌ๊ธฐ(AuthenticationProvider
)์๊ฒ ๋ก๊ทธ์ธ ๊ฒ์ฆ์ ๋ช ๋ นํ๋ค. ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ๋ฉด์์ ์ ๋ ฅํ ์์ด๋, ๋น๋ฐ๋ฒํธ๋ฅผ request์ ํจ๊ป ์ ์ก๋๊ณ ์ ๋ฌ๋ฐ์ ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ๋ง๋ค์ด๋RequestLogin
๋ก ๋ณํํ์ฌ ๋ก๊ทธ์ธ๊ฒ์ฆ์ฒ๋ฆฌ๊ธฐ์๊ฒ ์ ๋ฌํ๋ค- RequestLogin
@Data @AllArgsConstructor @NoArgsConstructor public class RequestLogin { @NotNull(message = "Email cannot be null") @Size(min = 2, message = "Email not be less than two characters") @Email private String email; @NotNull(message = "Password cannot be null") @Size(min = 8, message = "Password must be equals or greater than 8 characters") private String password; @NotNull(message = "Nickname cannot be null") @Size(min = 8, message = "Password must be equals or greater than 8 characters") private String nickName; }
- RequestLogin
successfulAuthentication
: ๋ก๊ทธ์ธ ๊ฒ์ฆ์ด ์ฑ๊ณตํ๋ค๋ฉด JWT ํ ํฐ์ ๋ฐํํ๊ณ ์ฟ ํค์ ํ ํฐ ๊ฐ์ ์ ์ฅํ๋คsetFailureHandler
: ๋ก๊ทธ์ธ ์คํจ์ ์คํํ ํธ๋ค๋ฌ๋ฅผ ์ฃผ์ ํด์ค๋ค.- ์ด ํจ์๋ ์์์ ๋ณธ WebSecurity์์
setFailureHandler
๋ฅผ ํธ์ถํ์ฌ ์ฌ์ฉํ๋๋ฐ ์ด ๋ ๋ง๋ค์ด๋ ์ปค์คํ ํธ๋ค๋ฌ๋ฅผ ์ฃผ์ ํด์ฃผ์๋ค(AuthFailureHandler)public class WebSecurity extends WebSecurityConfigurerAdapter { ... private final AuthFailureHandler authFailureHandler; private AuthenticationFilter getAuthenticationFilter() throws Exception { AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManager(), userService, env, jwtTokenProvider); authenticationFilter.setFailureHandler(authFailureHandler); //๋ก๊ทธ์ธ ์คํจ ํธ๋ค๋ฌ ์ฃผ์ return authenticationFilter; } ... }
- ์ด ํจ์๋ ์์์ ๋ณธ WebSecurity์์
3. ๋ก๊ทธ์ธ ๊ฒ์ฆ๊ธฐ
- ๋ก๊ทธ์ธ์ ๊ฒ์ฆํ๋ค
/**
* DB์ ์๋ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ํ ๋๋ก ๊ฒ์ฆ ์์
* @author ๊น์ฐฌ์
*/
@Component
@RequiredArgsConstructor
public class CustomAuthenticationProvider implements AuthenticationProvider {
private final PasswordEncoder passwordEncoder;
private final UserDetailsService customUserDetailsService;
/**
*
* @param authentication
* @return
* @throws AuthenticationException
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if(authentication == null){
throw new InternalAuthenticationServiceException("์ธ์ฆ ์ ๋ณด๊ฐ ์์ต๋๋ค");
}
String username = authentication.getName();
if(authentication.getCredentials() == null){
throw new AuthenticationCredentialsNotFoundException("Credentials์ด ์์ต๋๋ค");
}
String password = authentication.getCredentials().toString();
try {
/* ์ฌ์ฉ์ ์ ๋ณด ๋ฐ๊ธฐ */
UserDetails loadedUser = customUserDetailsService.loadUserByUsername(username);
if (loadedUser == null) {
throw new InternalAuthenticationServiceException("์ ์ ์ ๋ณด๊ฐ ์
๋ ฅ๋์ง์์์ต๋๋ค");
}
if (!loadedUser.isAccountNonLocked()) {
throw new LockedException("์ ๊ธด ๊ณ์ ์
๋๋ค");
}
if (!loadedUser.isEnabled()) {
throw new DisabledException("ํํดํ ๊ณ์ ์
๋๋ค");
}
if (!loadedUser.isAccountNonExpired()) {
throw new AccountExpiredException("๊ธฐํ ๋ง๋ฃ ๊ณ์ ์
๋๋ค");
}
/* ์ค์ง์ ์ธ ์ธ์ฆ ์์ */
if (!passwordEncoder.matches(password, loadedUser.getPassword())) {
throw new BadCredentialsException("ํจ์ค์๋๊ฐ ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค");
}
if (!loadedUser.isCredentialsNonExpired()) {
throw new CredentialsExpiredException("์ธ์ฆ๊ธฐํ์ด ๋ง๋ฃ๋์์ต๋๋ค");
}
/* ์ธ์ฆ ์๋ฃ */
UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(loadedUser, null, loadedUser.getAuthorities());
result.setDetails(authentication.getDetails());
return result;
}
catch (NoActivatedException e){
throw new NoActivatedException("ํด๋น ์์ด๋๋ ์์ต๋๋ค");
}
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
- try ๊ตฌ๋ฌธ ์์ชฝ
UserDetails loadedUser = customUserDetailsService.loadUserByUsername(username);
๋ฅผ ํตํด ๋ก๊ทธ์ธ ์ ๋ณด๋ฅผ ํ์ธํ๋ค. - customUserDetailsService๋ ์ธํฐํ์ด์ค
UserDetailsService
์ด๊ณ ๊ตฌํ์ฒด๋ ์ง์ ๋ง๋UserService
๋ฅผ ์ฌ์ฉํ๋ค- UserService
public class UserService implements UserDetailsService { ... @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserEntity userEntity = userRepository.findByEmail(username).orElseThrow(()->new NoActivatedException("ํด๋น์ ์ ๋ ์์ต๋๋ค")); // ์ญ์ ๋๊ณ์ ์ธ ๊ฒฝ์ฐ if(userEntity.getActive()=="0") return new User(userEntity.getEmail(), userEntity.getEncryptedPwd(), false, true, true, true, new ArrayList<>()); // ์ธ์ฆ์ด ๋์ง์์ ํ์ if(userEntity.getRole().equals(UserRole.ROLE_NOT_PERMITTED)) return new User(userEntity.getEmail(), userEntity.getEncryptedPwd(), true, true, true, false, new ArrayList<>()); return new User(userEntity.getEmail(), userEntity.getEncryptedPwd(), true, true, true, true, new ArrayList<>()); } ... }
- DB์์ ์ ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ์์ด๋/๋น๋ฐ๋ฒํธ๋ฅผ ์ฒดํฌํ๊ธฐ์ ์ DB์์ ๊ฐ์ ธ์จ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ์ ์ ์ ์ ํจ์ฑ ์ฒดํฌ๋ฅผ ์งํํ๊ณ ๊ทธ์ ๋ฐ๋ฅธ
User
๋ฅผ returnํ๋ค. ์ด๋User
๋ ์คํ๋ง ์ํ๋ฆฌํฐ์ ๊ฐ์ฒด์ด๋ค. - ์ ํจ์์์ ๋ฐํ๋ ๊ฐ์ด ํธ์ถํ
AuthenticationProvider
๋ก ์ ๋ฌ๋๋ค
- DB์์ ์ ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ ์์ด๋/๋น๋ฐ๋ฒํธ๋ฅผ ์ฒดํฌํ๊ธฐ์ ์ DB์์ ๊ฐ์ ธ์จ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ์ ์ ์ ์ ํจ์ฑ ์ฒดํฌ๋ฅผ ์งํํ๊ณ ๊ทธ์ ๋ฐ๋ฅธ
- UserService
loadUserByUsername
์ ์ํด ๋ฐํ๋ User๋ฐ์ดํฐ๋ฅผ ๊ฒ์ฆํ๋ค.passwordEncoder.matches(password, loadedUser.getPassword()
์์ ๋น๋ฐ๋ฒํธ ๊ฒ์ฆ์ ํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ๋ก๊ทธ์ธ ์ฑ๊ณต์ด ์๋ ๊ฒฝ์ฐ, Exception์ ๋์ง๊ณ ์ด Exception์AuthenticationFailureHandler
์์ ์ฒ๋ฆฌํ๋ค
4. ๋ก๊ทธ์ธ Exception Handler
@Component
public class AuthFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
// ํ๊ธ ์ฌ์ฉ
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String errorMsg = "";
if(exception instanceof AccountExpiredException){
response.setStatus(HttpServletResponse.SC_CONFLICT);
errorMsg = "๋ง๋ฃ๋ ํ์์
๋๋ค";
}
if(exception instanceof DisabledException){
response.setStatus(HttpServletResponse.SC_CONFLICT);
errorMsg = "ํํดํ ํ์์
๋๋ค";
}
if(exception instanceof NoActivatedException){
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
errorMsg = "์์ด๋๋ ํจ์ค์๋๊ฐ ์ฌ๋ฐ๋ฅด์ง์์ต๋๋ค.";
}
if(exception instanceof BadCredentialsException){
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
errorMsg = "์์ด๋๋ ํจ์ค์๋๊ฐ ์ฌ๋ฐ๋ฅด์ง์์ต๋๋ค.";
}
if(exception instanceof LockedException){
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
errorMsg = "์ด๋ฉ์ผ ์ธ์ฆ์ด ํ์ํฉ๋๋ค.";
}
response.getWriter().print(errorMsg);
response.getWriter().flush();
}
}
AuthenticationProvider
์์ ๋์ง Exception์ ๋ฐ๋ผ ์๋ฌ๋ฉ์ธ์ง๋ฅผ ํด๋ผ์ด์ธํธ์๊ฒ ๋ฐํํ์ฌ ๋ณด์ฌ์ค๋ค.
์ฌ๊ธฐ์ AuthFailureHandler
๋ ์ด๋์ ์ฃผ์
ํ๋๋ผ
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurity extends WebSecurityConfigurerAdapter {
private final UserService userService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final Environment env;
private final JwtTokenProvider jwtTokenProvider;
private final CustomAuthenticationProvider authProvider;
private final AuthFailureHandler authFailureHandler;
...
private AuthenticationFilter getAuthenticationFilter() throws Exception {
AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManager(), userService, env, jwtTokenProvider);
authenticationFilter.setFailureHandler(authFailureHandler); //๋ก๊ทธ์ธ ์คํจ ํธ๋ค๋ฌ ์ฃผ์
return authenticationFilter;
}
...
}
WebSecurity์์ setFailureHandler
๋ฅผ ํตํด ์ฃผ์
ํ๊ณ ์ด ํจ์๋ AuthenticationFilter
์์ ๊ตฌํ๋์๋ค.
@Slf4j
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private UserService userService;
private Environment env;
private final JwtTokenProvider jwtTokenProvider;
@Autowired
public AuthenticationFilter(AuthenticationManager authenticationManager,
UserService userService,
Environment env, JwtTokenProvider jwtTokenProvider){
this.jwtTokenProvider = jwtTokenProvider;
this.userService = userService;
this.env = env;
super.setAuthenticationManager(authenticationManager);
}
...
/**
* ์คํจ ํธ๋ค๋ฌ({@link AuthFailureHandler})๋ฅผ ์ง์ ์ฃผ์ํ๋ค
*/
public void setFailureHandler(AuthenticationFailureHandler failureHandler) {
Assert.notNull(failureHandler, "FailureHandler๊ฐ ์์ต๋๋ค");
super.setAuthenticationFailureHandler(failureHandler);
}
}
super
๋ฅผ ํตํด ๋ถ๋ชจํด๋์ค๋ฅผ ํ์ธํด๋ณด๋ฉด
๋ถ๋ชจํด๋์ค์์ ํด๋น ํจ์๊ฐ ๊ตฌํ๋์ด์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋๊ธ ์ฐ๊ธฐ