토큰 인증 방식은 request요청시 header에 담겨져 오는 token으로 로그인을 유
지하는 방식이다.
장점
단점
처음 로그인하는 경우 인증 방식
토큰이 헤더에 존재하는 경우 인증 방식
첫 로그인 구현하기
public JwtTokenDto login(String username, String password) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
username, password);
Authentication authentication = authenticationManagerBuilder.getObject()
.authenticate(authenticationToken);
return jwtTokenProvider.generateToken(authentication);
}
토큰이 헤더에 존재하는 경우 인증 요청 처리하기
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String token = resolveTokenFromRequest((HttpServletRequest) request);
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication authentication = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
세션 인증 방식은 서버에 세션저장소를 두어, 인증이 완료되면, SessionId를 생성해 세션 저장소에 해당 ID와 회원을 매핑해 둔 후 클라이언트에 반환해주는 방식이다.
장점
단점
처음 로그인하는 경우 인증 방식
헤더에 SessionId가 존재하는 경우 인증 방식
Spring Security에서는 기본적으로 세션-쿠키 방식을 사용하고 있다.
AbstractPreAuthenticatedProcessingFilter
private class PreAuthenticatedProcessingRequestMatcher implements RequestMatcher {
@Override
public boolean matches(HttpServletRequest request) {
Authentication currentUser = AbstractPreAuthenticatedProcessingFilter.this.securityContextHolderStrategy
.getContext().getAuthentication();
if (currentUser == null) {
return true;
}
if (!AbstractPreAuthenticatedProcessingFilter.this.checkForPrincipalChanges) {
return false;
}
if (!principalChanged(request, currentUser)) {
return false;
}
AbstractPreAuthenticatedProcessingFilter.this.logger
.debug("Pre-authenticated principal has changed and will be reauthenticated");
if (AbstractPreAuthenticatedProcessingFilter.this.invalidateSessionOnPrincipalChange) {
AbstractPreAuthenticatedProcessingFilter.this.securityContextHolderStrategy.clearContext();
HttpSession session = request.getSession(false);
if (session != null) {
AbstractPreAuthenticatedProcessingFilter.this.logger.debug("Invalidating existing session");
session.invalidate();
request.getSession();
}
}
return true;
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (this.requiresAuthenticationRequestMatcher.matches((HttpServletRequest) request)) {
if (logger.isDebugEnabled()) {
logger.debug(LogMessage.of(
() -> "Authenticating " + this.securityContextHolderStrategy.getContext().getAuthentication()));
}
doAuthenticate((HttpServletRequest) request, (HttpServletResponse) response);
}
else {
if (logger.isTraceEnabled()) {
logger.trace(LogMessage.format("Did not authenticate since request did not match [%s]",
this.requiresAuthenticationRequestMatcher));
}
}
chain.doFilter(request, response);
}
실제 AbstractPreAuthenticatedProcessingFilter의 matches메소드를 보면 SecurityContext에 인증객체가 존재하는지 확인한다.
실제 인증 객체가 존재하면 doAuthenticate()메소드를 통해 인증 객체의 인증을 진행하는 것을 볼 수 있다.