Spring Security UsernamePasswordAuthenticationToken 사용해보자
spring으로 개발한다고하면 한번쯤은 들어봤을 시큐리티.
처음에 공부하려고 열어봤다가 바로 닫았던 기억이 있네요.
Spring Security는 Java 애플리케이션에서 보안을 제공하는 강력한 프레임워크인데요.
시큐리티는 인증(Authentication)과 권한 부여(Authorization) 작업을 처리하는데 중점을 두고 있고, 다양한 보안 기능을 제공합니다.
그 중에서도 'UsernamePasswordAuthenticationToken' 클래스를 알아보겠습니다.
UsernamePasswordAuthenticationToken
'UsernamePasswordAuthenticationToken' 클래스는 사용자 인증을 처리하는 중요한 역할을합니다.
Spring Security에서 사용자 이름과 비밀번호를 기반으로 인증 요청을 나타내는 클래스입니다.
'AbstractAuthenticationToken'을 상속하며, 주로 사용자의 인증 정보를 캡슐화하고 인증 프로세스 중에 사용됩니다.
'UsernamePasswordAuthenticationToken'의 주요 목적은 사용자로부터 입력받은 사용자 이름과 비밀번호를 'AuthenticationManager'에 전달하여 인증을 수행하는겁니다.
주요 필드는
사용자 이름을 나타내는 principal
비밀번호는 credentials
사용자의 권한을 나타내는 authorities
입니다.
생성자
UsernamePasswordAuthenticationToken(Object principal, Object credentials)
인증되지 않은 상태에서 사용자 이름과 비밀번호를 사용하여 객체를 생성
UsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities)
인증된 사용자에서 사용자 이름, 비밀번호, 그리고 권한을 사용하여 객체를 생성
인증 과정
사용자의 로그인 요청 →
UsernamePasswordAuthenticationToken 객체 생성 →
AuthenticationManager로 인증 시도
늘 똑같이 사용자가 로그인 폼에 사용자 이름과 비밀번호를 입력하고 서버에 로그인 요청을 보내면
사용자의 입력 값 바탕으로 User...Token 객체가 생성됩니다.
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
생성된 User...Token 객체는 AuthenticationManager로 전달이됩니다.
AuthenticationManager는 여러 AuthenticationProvider를 사용하여 인증을 시도하는데 주로 DaoAuthenticationProvider가 사용됩니다.
DaoAuthenticationProvider 은 내부적으로 UserDetailsService를 사용하여 정보를 조회하고, 입력된 비밀번호와 데이터베이스에 저장된 비밀번호를 비교합니다.
인증에서 성공하면 Authentication 객체가 생성되고, 보안 컨텍스트(SecurityContext)에 저장됩니다.
SecurityContextHolder.getContext().setAuthentication(authentication);
사용
@PostMapping("/login")
public String login(String username, String password) {
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = authenticationManager.authenticate(authRequest);
SecurityContextHolder.getContext().setAuthentication(authentication);
return "redirect:/home";
}
스프링 시큐리티에서 제공하는 세션에 인증된 사용자의 정보를 저장하고
이를 타임리프와 같은 템플릿 엔진으로 사용하여 프로트엔드에서 쉽게 사용할 수 있도록 지원합니다.
securityContext는 HTTP 세션에 저장되며, 애플리케이션 전반에서 접근 가능합니다.
타임리프를 사용해서 사용자의 시큐리티 정보를 가져올 수 있게 되는거죠
[[${#authentication.details.userKey}]]
정리 전 자료... (공사중)
주요 클래스
UsernamePasswordAuthenticationFilter
attemptAuthentication()
successfulAuthentication()
AbstractAuthenticationProcessingFilter
doFilter()
attemptAuthentication()
UsernamePasswordAuthenticationToken
생성자: UsernamePasswordAuthenticationToken(Object principal, Object credentials)
생성자: UsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities)
AuthenticationManager
authenticate(Authentication authentication)
ProviderManager (AuthenticationManager의 구현체)
authenticate(Authentication authentication)
AuthenticationProvider
authenticate(Authentication authentication)
supports(Class<?> authentication)
AbstractUserDetailsAuthenticationProvider
authenticate(Authentication authentication)
retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
DaoAuthenticationProvider (AbstractUserDetailsAuthenticationProvider의 구현체)
retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
UserDetails
사용자의 정보를 담고 있는 인터페이스
UserDetailsService
loadUserByUsername(String username)
SecurityContextHolder
getContext()
setContext(SecurityContext context)
주요 메서드
FilterChainProxy
doFilter()
getFilters()
DelegatingFilterProxy
서블릿 필터를 통해 Spring Security 필터 체인을 실행
AbstractAuthenticationToken
isAuthenticated()
setAuthenticated(boolean isAuthenticated)
UsernamePasswordAuthenticationFilter
attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
AbstractUserDetailsAuthenticationProvider
preAuthenticationChecks(UserDetails user)
postAuthenticationChecks(UserDetails user)
createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user)
요청 수신: 사용자가 아이디와 비밀번호를 입력하고 로그인 요청을 보냅니다.
필터 체인 실행: FilterChainProxy가 DelegatingFilterProxy에 의해 호출되며, 여러 필터가 순차적으로 실행됩니다.
인증 필터: UsernamePasswordAuthenticationFilter가 실행되어 attemptAuthentication() 메서드를 호출합니다.
인증 토큰 생성: UsernamePasswordAuthenticationToken 객체가 생성됩니다.
AuthenticationManager 호출: getAuthenticationManager()를 통해 AuthenticationManager가 호출되고, authenticate() 메서드가 실행됩니다.
AuthenticationProvider 확인: ProviderManager가 각 AuthenticationProvider를 순회하며 적절한 Provider를 찾습니다.
인증 로직 실행: DaoAuthenticationProvider에서 retrieveUser()와 additionalAuthenticationChecks()를 통해 사용자 정보를 검증합니다.
인증 완료: 인증이 완료되면 인증된 UsernamePasswordAuthenticationToken 객체가 생성되어 반환됩니다.
Security Context에 저장: 인증된 Authentication 객체가 SecurityContextHolder에 저장됩니다.