티스토리 뷰
1. unauthorizedHandler 비인증 처리
- AuthEntryPointJwt
@Component // 인증,인가 예외발생시 처리
public class AuthEntryPointJwt implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "가입하지 않은 아이디이거나, 잘못된 비밀번호입니다.");
}
}
- 인증과정에서 실패하거나 인증헤더(Authorization)를 보내지 않게되는 경우 401 라는 응답값을 받게된다.
이를 처리해주는 로직이 AuthenticationEntryPoint이다.
React의 로그인 페이지에서 회원 정보가 없을 경우 에러 메세지를 주기 위해서 response.sendError( ) 쓴다.
2. JwtToken 생성
- JwtToken
@Component
public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
@Value("${jwt.app.jwtSecret}")
private String jwtSecret;
@Value("${jwt.app.jwtExpirationMs}")
private int jwtExpirationMs;
public String generateJwtToken(Authentication authentication) {
UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
return Jwts.builder()
.setSubject((userPrincipal.getUsername())) // payload
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
}
- Authentication 객체의 getPrincipal() 메서드를 실행하게 되면, UserDetails를 구현한 사용자 객체를 Return 한다.
UserDetails를 구현한 객체가 가지고 있는 정보들을 가져올 수 있다. 가져온 정보들을 Jwt 토큰에 builder( ) 하여 이름, 현재 시간, 토큰 시간, 개인 비밀키를 넣어 토큰을 생성한다.
- getUserNameFromJwtToken(Strign token)는 인증된 회원들을 loadUserByUsername(username)에 담기 위함이다.
3. AuthTokenFilter 생성
- AuthTokenFilter
public class AuthTokenFilter extends OncePerRequestFilter {
.....
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
String jwt = parseJwt(request);
if (jwt != null) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication); // 현재 세션의 사용자 정보를 가져옴
}
} catch (Exception e) {
logger.error("Cannot set user authentication: {}", e);
}
filterChain.doFilter(request, response);
}
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7, headerAuth.length());
}
return null;
}
}
- header에서 Authorization 값을 가져오고 그 값이 있거나 startWith 시작하는 부분이 Bearer로 시작한다면 headerAuth.substring 리턴한다.
- doFilterInternal에서 Jwt 토큰이 있다면 authentication에 username, role를 넣고 수동으로 인증을 설정하도록 스프링 시큐리티를 구성한다.
- SecurityContextHolder( ) 통해 현재 사용자 정보를 authentication 통해 담아준다.
'∙React + Spring' 카테고리의 다른 글
회원가입,로그인,로그아웃 기능,경로 설정(react + spring boot ) (0) | 2021.08.17 |
---|---|
spring boot JWT 인증 #4 (Controller) (0) | 2021.08.17 |
spring boot JWT 인증 #2 (model, repository, userDetails, configAdapter) (0) | 2021.08.17 |
spring boot JWT 인증 #1 (0) | 2021.08.17 |