formLogin()을 이용하는 방식이다. 폼 로그인 방식을 이용하면 시큐리티가 제공하는 UsernamePasswordAuthenticationFilter
의 attemptAuthentication()
이 호출된다.
formLogin().disable()할 경우의 구조다. 디폴트 방식인 폼 로그인을 사용하지 않으면 UsernamePasswordAuthenticationFilter
를 사용할 수 없다. 그러면 어떻게 해야 할까?
방법은 해당 필터를 상속한 커스텀 필터를 만들고, 이를 필터로 추가하는 설정을 넣는 것이다.
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//login 요청해서 username,password post 전송하면 UsernamePasswordAuthenticationFilter 가 동작을 함.
//그런데 formLogin.disable()하면 해당 필터가 작동 안함.
//따라서 다시 동작시키려면 필터 체인에 다시 등록해야 함.
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
//로그인 시도 할때 호출되는 메서드
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
System.out.println("로그인 시도중");
//1. username, password 받아서
//2. 정상인지 authenticationManager 로 로그인 시도를 해봄.
//3. 그러면 PrincipalDetailsService 의 loadUserByUsername()이 실행됨.
//4. 리턴된 PrincipalDetails 를 세션에 담는다. (권한 관리를 위해서 세션에 담는다.)
//5. JWT 토큰을 만들어서 응답해준다.
return super.attemptAuthentication(request, response);
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
...
.formLogin().disable()//JWT 방식이라 폼로그인 필요 없음. 즉, 로그인 폼이 필요 없음.
.addFilter(new JwtAuthenticationFilter(authenticationManager()))//로그인을 담당해주는 AuthenticationManger 를 담아야 함. 해당 객체는 securityConfig 가 갖고 있음.
...
}
구조는 다음과 같다.