ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Security JWT - JWT를 통한 인증
    Framework & Library/Spring Security 2021. 10. 10. 19:42

    JWT 검증

    JwtAuthorizationFilter 클래스 생성
    public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
    
        private UserRepository userRepository;
    
        public JwtAuthorizationFilter(AuthenticationManager authenticationManager, UserRepository userRepository) {
            super(authenticationManager);
    
            this.userRepository = userRepository;
        }
    
        @Override
        /** 인증이나 권한이 필요한 주소요청이 있을 때 실행되는 메서드 */
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
            System.out.println("인증이나 권한이 필요한 주소 요청");
    
            String jwtHeader = request.getHeader("Authorization");
            System.out.println("jwtHeader : " + jwtHeader);
    
            /* 클라이언트 측에서 전달받은 JWT가 올바른지 확인 */
            if (jwtHeader == null || !jwtHeader.startsWith("Bearer")) {
                chain.doFilter(request, response);
                return;
            }
    
            /* 클라이언트 측에서 전달받은 JWT 검증 */
            String jwtToken = request.getHeader("Authorization").replace("Bearer ", "");
    
            String username = JWT.require(Algorithm.HMAC512("qlsdud0604")).build().verify(jwtToken).getClaim("username").asString();
    
            /* JWT 검증이 올바르게 된 경우 */
            if (username != null) {
                User userEntity = userRepository.findByUsername(username);
    
                PrincipalDetails principalDetails = new PrincipalDetails(userEntity);
    
                Authentication authentication = new UsernamePasswordAuthenticationToken(principalDetails, null, principalDetails.getAuthorities());
    
                SecurityContextHolder.getContext().setAuthentication(authentication);   // 시큐리티 세션 공간에 Authentication 저장
    
                chain.doFilter(request, response);
            }
        }
    }

     로그인을 한 사용자가 권한이 필요한 페이지에 접근을 할 때 해당 사용자의 JWT를 이용한 인증 과정이 필요하다

     해당 과정을 처리하는 클래스인 JwtAuthorizationFilter 클래스를 jwt 패키지 내에 생성하고 BasicAuthenticationFilter 클래스를 상속받는다.

     BasicAuthenticationFilter 클래스는 시큐리티가 가지고 있는 필터 중 하나이며, 권한이나 인증이 필요한 특정 주소에 접근했을 때 해당 필터를 반드시 거치게 된다.

     doFilterInternal() 메서드에서는 클라이언트 측으로부터 전달받은 JWT를 검증하는 코드가 들어간다.

     JWT의 검증이 정상적으로 완료가 되면 클라이언트는 권한이 필요한 주소에 접근이 가능해진다.

     

    JwtAuthorizationFilter 필터 등록

     

    ㆍ JwtAuthorizationFilter 클래스가 필터의 역할을 수행하기 위해서는 시큐리티 필터에 등록을 해야 한다.

    ㆍ SecurityConfig 클래스에 UserRepository 객체를 선언하고 .addFilter() 메서드를 이용해서 JwtAuthorizationFilter 클래스를 시큐리티 필터에 등록한다.

     

    RestApiController 클래스 수정
    /* user, manager, admin 권한 접근 가능 */
    @GetMapping("/api/v1/user")
    public String user() {
        return "user";
    }
    
    /* manager, admin 권한 접근 가능 */
    @GetMapping("/api/v1/manager")
    public String manager() {
        return "manager";
    }
    
    /* admin 권한 접근 가능 */
    @GetMapping("/api/v1/admin")
    public String admin() {
        return "admin";
    }

    ㆍ JWT 인증을 테스트하기 위해 RestApiController 클래스에 위 메서드들을 추가한다.

    ㆍ 각 메서드들과 매핑된 주소에 접근하기 위해서는 서로 다른 권한이 요구된다.


    테스트

    로그인 요청

     

    ㆍ username의 값을 "qlsdud0604"로 password의 값을 "1234"로 지정한 후 JSON 형태로 로그인 요청을 한다.

     

    Header 정보 확인

     

    ㆍ 로그인 요청을 한 후 서버 측에서 발급한 JWT 정보를 Header를 통해 확인한다.

     

    "/api/v1/user" 주소 접근

     

    ㆍ 로그인이 된 상태에서 서버로부터 발급받은 JWT를 Header에 포함하여  "/api/v1/user" 주소에 접근한다.

    ㆍ ROLE_USER 권한을 가진 사용자는 해당 주소에 접근이 가능한 것을 확인할 수 있다.

     

    "/api/v1/manager" 주소 접근

     

    ㆍ 로그인이 된 상태에서 서버로부터 발급받은 JWT를 Header에 포함하여  "/api/v1/manager" 주소에 접근한다.

    ㆍ ROLE_USER 권한을 가진 사용자는 해당 주소에 접근이 불가능한 것을 확인할 수 있다.

     

    "/api/v1/admin" 주소 접근

     

    ㆍ 로그인이 된 상태에서 서버로부터 발급받은 JWT를 Header에 포함하여  "/api/v1/admin" 주소에 접근한다.

    ㆍ ROLE_USER 권한을 가진 사용자는 해당 주소에 접근이 불가능한 것을 확인할 수 있다.


     

    GitHub - qlsdud0604/spring-security-basic: 스프링 시큐리티의 기초를 학습하는 공간

    스프링 시큐리티의 기초를 학습하는 공간. Contribute to qlsdud0604/spring-security-basic development by creating an account on GitHub.

    github.com

     

    728x90

    댓글

Designed by Tistory.