Spring Security + JWT 7

johaS2·2025년 2월 4일

JWT 검증 필터 구현

// JWTFilter는 시큐리티 필터 중 하나로, HTTP 요청을 가로채서 JWT 토큰을 검증하는 역할을 한다!
// 요청에서 JWT토큰을 찾고 > 유효한지 검증 > 유효하면 사용자의 정보를 인증 정보로 설정하는 필터
public class JWTFilter extends OncePerRequestFilter {
    // OncePerRequestFilter는 Spring Security의 필터로, 요청당 한번만 실행됨
    // 필터는 HTTP 요청과 응답을 처리하는 중간에 들어가서 특정 로직을 실행 할 수 있게 해준다.

    // JWTUtil (JWT 생성하고 , 검증하는 메서드를 가지고 있는 클래스) 객체 주입!
    private final JWTUtil jwtUtil;

    public JWTFilter(JWTUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    // doFilterInternal 메서드는 요청이 들어올 때마다 실행된다.
    // 여기서 JWT를 검증하고, 인증 정보를 세팅해주고, 요청을 필터 체인에 전달하는 역할을 합니다
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        //request에서 Authorization 헤더를 찾음
        String authorization= request.getHeader("Authorization");

        //Authorization 헤더 검증
        if (authorization == null || !authorization.startsWith("Bearer ")) {
            // authorization 헤더가 없거나 Bearer 로 시작하지 않으면
            // 토큰이 없는 것으로 간주하고 요청을 필터 체인에 넘긴다
            System.out.println("token null");
            filterChain.doFilter(request, response);

            //조건이 해당되면 메소드 종료 (필수)
            return;
        }

        System.out.println("authorization now");
        // Bearer 부분 제거 후 순수 토큰만 추출 !
        String token = authorization.split(" ")[1];

        //토큰 소멸 시간 검증
        if (jwtUtil.isExpired(token)) {
            // 만료된 토큰이라면 요청을 필터 체인에 넘기고 종료 !
            System.out.println("token expired");
            filterChain.doFilter(request, response);

            //조건이 해당되면 메소드 종료 (필수)
            return;
        }

        //토큰에서 username과 role 획득
        String username = jwtUtil.getUsername(token);
        String role = jwtUtil.getRole(token);

        //userEntity 객체를 생성하여 값 set
        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(username);
        userEntity.setPassword("temppassword"); // 임시 비밀번호 설정값임
        userEntity.setRole(role);

        // CustomUserDetails 객체 생성 -> security의 인증 정보로 사용
        CustomUserDetails customUserDetails = new CustomUserDetails(userEntity);

        // Authentication 객체 생성 - 스프링 시큐리티 인증 토큰 생성
        // UsernamePasswordAuthenticationToken
        // -> security에서 인증된 사용자 정보를 담는 객체, customUserDetails 를 이용하여 인증 정보 생성
        Authentication authToken = new UsernamePasswordAuthenticationToken(customUserDetails, null, customUserDetails.getAuthorities());

        // SecurityContext에 인증 정보 저장 - 세션에 사용자 등록
        SecurityContextHolder.getContext().setAuthentication(authToken);

        // 필터 체인 계속 진행
        filterChain.doFilter(request, response);

    }
}

SecurityConfig에 JWTFilter 등록

http
                .addFilterBefore(new JWTFilter(jwtUtil), LoginFilter.class);

JWT 필터 통과 후 세션 확인

@Controller
@ResponseBody //특정한 문자열을 반환을 위해서 @ResponseBody
public class MainController {

    @GetMapping("/")
    public String mainP(){

        String username = SecurityContextHolder.getContext().getAuthentication().getName();

		// 사용자 role
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        Iterator<? extends GrantedAuthority> iter = authorities.iterator();
        GrantedAuthority auth = iter.next();
        String role = auth.getAuthority();

        return "main Controller" + username + " " + role;
    }
}
profile
passionate !!

0개의 댓글