ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Delivery Together - JWT 인증방식의 로그인(4)
    Projects/Problem & Solution 2021. 12. 26. 20:33

    개요

    이전 게시물에서 사용자 로그인 정보를 통해 JWT를 발급하는 과정까지 알아보았다. 이번에는 발급한 JWT를 통해 어떠한 방식으로 정보 교류가 이루어지는지 알아보도록 하겠다.


    JWT 인증

    JwtAuthenticationFilter 클래스
    public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
        private UserDetailsService userDetailsService;
    
        private JwtTokenHelper jwtTokenHelper;
    
        public JwtAuthenticationFilter(UserDetailsService userDetailsService, JwtTokenHelper jwtTokenHelper) {
            this.userDetailsService = userDetailsService;
            this.jwtTokenHelper = jwtTokenHelper;
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            String authToken = jwtTokenHelper.getToken(request);   // 클라이언트 요청에 대한 JWT
    
            /* 토큰 정보가 존재하는 경우 */
            if (authToken != null) {
                String username = jwtTokenHelper.getUsernameFromToken(authToken);
    
                /* 토큰의 username이 존재하는 경우 */
                if (username != null) {
                    UserDetails userDetails = userDetailsService.loadUserByUsername(username);
    
                    /* 토큰이 유효한 경우 */
                    if (jwtTokenHelper.isTokenValidate(authToken, userDetails)) {
                        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
    
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    }
                }
            }
            filterChain.doFilter(request, response);
        }
    }

    위 클래스는 JWT를 이용해서 클라이언트 인증을 수행하는 클래스이다. 즉, 토큰의 유형성을 검사하는 클래스이다.

     JwtAuthenticationFilter 클래스는 OncePerRequestFilter 클래스를 상속받는 형태로 구성되어 있다.

    우선, JWT의 유효성을 검사한 후 유효한 토큰으로 판명된 경우 토큰으로부터 얻은 UserDetails 객체와 권한 정보를 이용해서 UsernamePasswordAuthenticationToken 객체를 생성한다.

    생성된 UsernamePasswordAuthenticationToken 객체를 SecurityContextHolder.getContext().setAuthentication() 메서드를 통해서 SecurityContextHolder에 집어넣음으로써 인증이 완료된다.

     

    OncePerRequestFilter란? 

    OncePerRequestFilter는 이름에서도 알 수 있듯이 모든 서블릿에 일관된 요청을 처리하기 위해 만들어진 필터이다. 이 추상 클래스를 구현한 필터는 사용자의 한번에 요청 당 딱 한 번만실행되는 필터를 만들 수 있다.

     

    UsernamePasswordAuthenticationToken 

    UsernamePasswordAuthenticationToken 클래스는 Authentication 인터페이스를 구현한 클래스로, 사용자의 인증이 완료된 후 최종적으로 Spring Security에게 전달해주는 구현체이다.


    사용자 정보 받기

    컨트롤러 생성
    @GetMapping("/auth/userinfo")
    public ResponseEntity<?> getUserInfo(Principal user) throws Exception {
        User userEntity = (User) userServiceImpl.loadUserByUsername(user.getName());
    
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername(userEntity.getUsername());
        userInfo.setBirthdate(userEntity.getBirthdate());
        userInfo.setCountry(userEntity.getCountry());
        userInfo.setGender(userEntity.getGender());
    
        return new ResponseEntity<>(userInfo, HttpStatus.OK);
    }

    로그인을 성공적으로 수행한 사용자가 자신의 프로필 페이지에 필요한 정보를 받기 위한 메서드이다.

    로그인이 완료되면서 발급받은 JWT를 Header를 통해서 서버 측으로 전송한다.

    서버 측에서는 JwtAuthenticationFilter 클래스를 통해 JWT의 유효성을 검사하고, 검사가 완료되면 JWT로부터 생성된 Authentication 객체를 SecurityContextHolder에 집어넣는다.

     

     

    SecurityContextHolder안에 Authentication 객체는 Principal을 포함하고 있기 때문에, 컨트롤러에서도 접근이 가능하다.


    테스트

    1.  로그인 요청

     

    사용자가 로그인을 수행하기 위해 username과 password를 서버 측으로 요청한다.

     

    2. JWT 발급

     

    로그인이 성공적으로 완료가 되면, 서버 측에서 사용자 정보를 통해 만들어진 JWT를 발급한다.

     

    3. 사용자 정보 요청

     

    로그인 사용자의 정보를 요청하기 위해 발급받은 JWT를 Header에 포함하여 컨트롤러의 주소로 전송한다.

     

     

    JWT 검증이 완료되면 로그인 사용자에 대한 정보가 올바르게 응답되는 것을 확인할 수 있다.


     

    GitHub - yu-capstone-design/delivery-together: 🍕 배달 주문을 같이할 사용자를 찾도록 매칭 서비스를 제공

    🍕 배달 주문을 같이할 사용자를 찾도록 매칭 서비스를 제공해주는 애플리케이션. Contribute to yu-capstone-design/delivery-together development by creating an account on GitHub.

    github.com

     

    728x90

    댓글

Designed by Tistory.