OncePerRequestFilter를 상속 받아 JWT로 인증을 진행하는 JwtAuthenticationFilter를 생성한다. JwtAuthenticationFilter에서는 요청이 들어왔을 때 Token이 있는지 확인하고 해당 Token을 이용해 인증을 진행한 후 AuthenticationToken을 생성해 SecurityContextHolder에 저장한다.
UsernamePasswordAuthenticationToken
사용자의 Username과 Password를 이용하여 AuthenticationToken을 생성한다.
Username과 Password를 이용해 /api/user/login 경로로 인증을 시도하면 AuthenticationManager 객체를 이용해 인증을 진행하고 인증이 성공적으로 완료 되면 JWT를 생성해 Header에 JWT를 넣어 Status code : 200과 함께 반환한다.
try { // AuthnRequest로부터 받은 username과 password를 이용하여 UsernamePasswordAuthenticationToken을 생성한 후 // 생성된 토큰을 이용해 인증을 시도한다. authenticationManager.authenticate( newUsernamePasswordAuthenticationToken(username, password)); } catch (Exception ex) { thrownewException("inavalid username/password"); }
// 인증이 정상적으로 이루어진 경우 username을 이용해 JWT를 생성해 반환한다. returnnewResponseEntity(httpHeaders, HttpStatus.OK); }
권한을 갖고 접근하기 위한 Controller 추가
반환받은 JWT를 갖고 /api/user/access 경로로 접근하면 Permission to Access 문구가 반환된다.
JwtController.java
@GetMapping("/access") public String accessByToken(){ return"Permission to Access"; }
Security 설정 추가하기
AuthenticationManagerBuilder객체의 userDetailsService 메소드를 이용해 사용자가 정의한 CustomUserDetailsService 객체를 사용하도록 등록한다.
SecurityConfig.java
@Override protectedvoidconfigure(AuthenticationManagerBuilder auth)throws Exception { // 사용자가 정의한 UserDetailsService를 사용한다. auth.userDetailsService(customUserDetailsService); }
회원가입을 위한 /api/user/signup 경로와 로그인을 위한 /api/user/login 경로는 인증전에 접근하기 위한 경로이므로 권한 없이 접근 가능해야 한다. 그외 모든 경로는 인증된 사용자만 접근 할 수 있도록 설정한다.
사용자 정의 Filter인 JwtAuthenticationFilter를 Spring Filter에 추가한다.
SecurityConfig.java
@Override protectedvoidconfigure(HttpSecurity http)throws Exception { http.csrf().disable().authorizeRequests() .antMatchers("/api/user/login").permitAll() .antMatchers("/api/user/signup").permitAll() .anyRequest().authenticated() .and() // 토큰을 활용하면 세션이 필요 없으므로 STATELESS로 설정하여 Session을 사용하지 않는다. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() // form 기반의 로그인에 대해 비활성화 한다. .formLogin().disable() // 새롭게 정의한 Filter를 등록한다. .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); }