해당 url로
{
"email":"user",
"password":"1111"
}
데이터를 바디에 담아 요청하면
토큰이 발행되도록 만들려고 한다.
Spring 2.7.0 기준
일단 먼저일반적으로 Spring Security에 로그인 요청을 날리면 UsernamePasswordAuthenticationFitler로 해당 아이디, 비밀번호 입력값이 해당 필터로 날라간다.
하지만 JWT의 경우 폼로그인이 아닌 json 데이터로 들어온 값을 DB값과 대조하여 맞을 경우 토큰을 던져줘야 한다.
그래서 UsernamePasswordAuthentciationFilter 자리를 뺏기로 했다.
하지만 UsernamePasswordAuthenticationFilter는 특징이 있어 이 특징을 잘 처리해줘야한다.
1. 해당 FIlter를 거치고 다음 Filter로 가지 않는다. 그렇기 때문에 인증 성공 여부에 따른 메서드 successAuthenticaiton/unSuccessfulAuthentication을 구현해야한다.
2. 해당 필터는 /login으로 접근할 때만 동작한다. 그렇기 때문에 해당 URL을 변경해줘야한다.
그러므로 자리를 뺏기전에 해당 설정을 해줘야 한다.
LoginSuccessHandler successHandler = new LoginSuccessHandler(jwtUtil);
LoginFailureHandler failureHandler = new LoginFailureHandler();
loginFilter.setAuthenticationSuccessHandler(successHandler);
loginFilter.setAuthenticationFailureHandler(failureHandler);
loginFilter.setFilterProcessesUrl("/token/login");
성공했을 시 Handler를 통해 동작을 조작할 수 있다. 성공을 하면 토큰을 보내주고 실패하면 실패 메시지를 던지는 핸들러들이다.
http.authorizeHttpRequests(auth -> {
auth.anyRequest().permitAll();
})
.addFilterAt(loginFilter, UsernamePasswordAuthenticationFilter.class)
addFilterAt으로 UsernamePasswordAuthenticationFIlter 자리를 뺴았는다.
여기서 모든 요청을 열어둔 건 테스트를 위함이지 별다른 뜻은 없다.
기존에 있는 UsernamePasswordAuthenticationFIlter의 코드를 조금 수정해서 오버라이딩한다. 크게 다른 점은 없지만 있다면 기존 필터는 form 데이터에서 값을 추출하지만 여기서는 request에서 입력값을 추출한다. jsonParser메서드를 통해 email과 password를 추출해 token으로 만들어 AuthenticationManager에게 넘긴다.
AuthenticationManager는 해당 Authentication 객체를 처리할 Provider 들을 가지고 있고 그걸 처리할 Provider를 찾아 위임한다. 구현체가 ProviderManager이므로 ProviderManager.authenticate 가 Provider를 찾는다.
AbstractUserDetailsAuthenticationProvider 당첨
userCache에서 없다면 retrieveUser를 실행한다.
참고로 여기서 retrieeveUser에서 넘기는 username은
우리가 보낸 토큰에서 이름을 추출하는 것이다.
다음으로 DaoAuthenticationProvider로 넘어온다.
우리가 구현한 UserDetailsService에서 값을 UserDetails 값을 넘겨 받는다.
이렇게 우리가 넘긴 email,password로 만든 토큰과 해당 email로 조회한 UserDetails객체랑 비교할 것이다.
다시 AbstractUserDetailsAuthenticationProvider 로 넘어와서
권한체크와 비밀번호체크를 시작한다.
비밀번호를 체크하는 메소드는 DaoAuthenticationProvider이다
그렇게 권한을 추가해주고
ProviderManager에게 돌아간다.
그러고 -> AbstractAuithenticationProcessingFilter -> 를 거치면서
우리가 만든 핸들러에 도착하게 된다..... 핸들러에서는 토큰을 발행하여 던져준다.
'Spring Security' 카테고리의 다른 글
Spring Security - UserDetails 대신 다른 객체 넣기 (0) | 2023.04.19 |
---|---|
SpringSecurity - UsernamePasswordAuthenticationFilter (0) | 2023.02.15 |
Spring Security - 2.7 이후 SecurityFilterChain (0) | 2023.01.02 |