ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OAuth2.0과 JWT적용 - 3
    스프링 2023. 1. 25. 22:17

    처음 들어오는 사용자가 OAuth로그인 후 -> 처음 들어오는 사용자면 DB에 정보 저장후 -> 토큰 발급

     

    이러한 로직을 수행하려고 한다.

     

    우선 Controller를 먼저 구성해보자

    @RestController
    @RequiredArgsConstructor
    public class MemberController {
    
        private final OAuthService oAuthService;
    
        @GetMapping("/oauth/login")
        public ResponseEntity<Token> loginController(@AuthenticationPrincipal OAuth2User oAuth2User) {
            return ResponseEntity.ok(oAuthService.login(oAuth2User.getAttributes()));
        }
    }

    return되는 저것은 우선 신경쓰지 말자.

    전에 구성했던 OAuthUserService를이용해 loadUser로 대항 OAuth인증을 하는 사용자 정보를 가지고 온다. 

    (https://winwin-k9.tistory.com/106 이전글은 여기 참고)

     

    스프링 시큐리티는 SecurityContext에 인증된 Authentication 객체를 넣어두고 현재 스레드 내에서 공유되도록 관리한다.

     

    OAuthService

    @Service
    @RequiredArgsConstructor
    public class OAuthService {
        private final MemberRepository memberRepository;
        private final TokenService tokenService;
    
        @Transactional
        public Token login(Map<String, Object> attribute) {
            String email = (String) attribute.get("email");
            String name = (String) attribute.get("name");
            if (memberRepository.findByEmail(email) == null) {
                Member member = new Member(email, name);
                memberRepository.save(member);
            }
            return tokenService.generateToken(email, name);
        }
    }

     

    OAuth인증 사용자로 부터 Attribute를 가져온다. 인증된 사용자의 Attribute는 속성으로 Map구조로 되어있다.

    이 정보를 받아서 해당 유저가 DB에 이미 저장이 되어있지 않으면 정보를 저장(회원가입 처리)후

    토큰을 발급해주도록 한다.

     

    다음은 Security설정이다.

     

    @Configuration
    @EnableWebSecurity
    @RequiredArgsConstructor
    public class SecurityConfig {
        private final OAuthUserService oAuthUserService;
        private final JwtFilter jwtFilter;
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return PasswordEncoderFactories.createDelegatingPasswordEncoder();
        }
    
        @Bean
        public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            http
                    .cors()
                    .and()
                    .csrf().disable()
                    .authorizeHttpRequests().anyRequest().permitAll()
                    .and()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) //세션사용 안함
                    .and()
                    .formLogin()
                    .and()
                    .oauth2Login()  //OAuthLogin 설정
                    .userInfoEndpoint() // oauth2Login 설정을 시작
                    .userService(oAuthUserService) // 로그인을 oAuthUserService에서 처리
                    .and()
                    .defaultSuccessUrl("/oauth/login");
            http.addFilter(jwtFilter);
    
            return http.build();
        }
    }

     

    OAuth로그인이 끝나면 url이 defaultSuccessUrl인 /oauth/login 으로 이동하게 된다.

    여기서 오류가 발생하는데

     

    does not have a registered order and cannot be added without a specified order

    addFilter는 메서드를 사용하기 위해서는 반드시 Spring Security Framework 에서 제공되는 필터 혹은 이를 확장한 객체이어야 한다. 

    따라서 addFilterBefore나 After를 사용해야 한다.

     

    따라서 다음과 같이 변경해야 한다.

    http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);

    UsernamePasswordAuthenticationFilter는 Form인증을 처리하는 필터이다.

    사용자가 로그인하면 인증처리가 이루어지는데, 이 인증처리를 담당하고 관련된 요청을 처리한다.

     

     

    http://localhost:8080/oauth2/authorization/google

    OAuth인증을 하는 해당 URL로 접속후, 로그인을 하면

    아래와 같이 토큰을 발급받는것을 확인할 수 있다.

    728x90

    '스프링' 카테고리의 다른 글

    API 예외처리-2  (0) 2023.01.27
    API 예외처리-1  (0) 2023.01.26
    UsernamePasswordAuthenticationFilter  (0) 2023.01.19
    JWT 토큰 체크  (0) 2023.01.19
    OAuth2.0과 JWT적용 - 2  (0) 2023.01.17

    댓글

Designed by Tistory.