スプリングセキュリティプリファレンス-セキュリティ4編


完全なフローチャートは、前の記事で見つけなければなりません.
https://velog.io/@jjy5349/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-%EA%B8%B0%EB%B3%B8-%EC%84%A4%EC%A0%95SecurityConfig.class-JwtTokenProvider.class-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-3%ED%8E%B8
JwtExceptionFilter
@Slf4j
@RequiredArgsConstructor
public class JwtExceptionFilter extends OncePerRequestFilter {

    private final ObjectMapper objectMapper;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");

        try{
            filterChain.doFilter(request, response);
        } catch (IncorrectDeleteUserRequestException e){
            Map<String, String> map = new HashMap<>();

            map.put("errortype", "Forbidden");
            map.put("code", "402");
            map.put("message", "잘못된 토큰 또는 이미 삭제된 회원입니다.");

            log.error("삭제된 유저의 토큰으로 접근");
            response.getWriter().write(objectMapper.writeValueAsString(map));
        }
    }
}
JwtException Filterは「認証」段階でthrow new Exception()を行い、再び逆行してフローチャートのチェーンに乗ります.
この場合、例外ごとに例外処理を行うことができます.私の場合、I n c o r rectDeleteUserRequestExceptionという例外を作成して使用しました(本明細書では例外処理については説明しません).
追加の説明
JWTAuthenticationFilterにJWTProviderが登録されたため、これまでプロジェクトにJWTException Filter例外が1つしか登録されていませんでした.validateメソッドを読み込みますが、ここで例外を投げ出すと、フローチャート全体に表示されるCustomEntryPointは取得できず、再びフィルタを反転させます.したがって、この部分は開発者のカスタマイズに必要な部分です.
私の場合、削除したユーザーの再削除を要求する際にJwtException Filterで処理しなければならないため、I n c o r rectDeleteUserRequestExceptionが登録されています.
JwtAuthenticationFilter
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends GenericFilterBean {

    private final JwtTokenProvider jwtTokenProvider;

    /**
     * methodName : doFilter
     * author : Jaeyeop Jung
     * description : AccessToken을 검증하고, 해당 유저를 찾아 권한처리를 위해 Context에 담는다.
     *
     * @param request  the request
     * @param response the response
     * @param chain    the chain
     * @throws IOException      the io exception
     * @throws ServletException the servlet exception
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String token = null;
        if(httpRequest.getHeader("Authorization") != null && httpRequest.getHeader("Authorization").startsWith("Bearer ")){
            token = httpRequest.getHeader("Authorization").split(" ")[1];
        }

        if( token != null && jwtTokenProvider.validateToken(token) ) {
            Authentication authentication = jwtTokenProvider.getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        chain.doFilter(httpRequest, httpResponse);
    }
}
今は重要なWTAuthenticationFilterです
このフィルタは、HTTPリクエストに含まれるAccessTokenを検証し、検証が完了した後に検証します.
        if( token != null && jwtTokenProvider.validateToken(token) ) {
            Authentication authentication = jwtTokenProvider.getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
このコードはSecurityContextHolderに含まれています.
チェーンが入っていなければdoFilterで次のフィルタに移動すると、CustomEntryPointに移動します.
CustomEntryPoint
@Component
@RequiredArgsConstructor
@Slf4j
public class CustomEntryPoint implements AuthenticationEntryPoint {

    private final ObjectMapper objectMapper;

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        response.setCharacterEncoding("utf-8");
        log.warn("CustomEntryPoint : 잘못된 토큰으로 페이지 요청");

        response.setStatus(HttpServletResponse.SC_FORBIDDEN);

        Map<String, String> map = new HashMap<>();
        map.put("errortype", "Forbidden");
        map.put("code", "403");
        map.put("message", "잘못된 토큰으로 접근하였습니다. 다시 로그인 해주세요");

        response.getWriter().write(objectMapper.writeValueAsString(map));
    }
}
次はCustomEntryPointです.ここでは誤ったトークンを使用したことをお知らせし、HTTP応答の内容を記入するだけです.
CustomAccessDeniedHandler
@Component
@RequiredArgsConstructor
@Slf4j
public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    private final ObjectMapper objectMapper;

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setCharacterEncoding("utf-8");
        log.warn("CustomAccessDeniedHandler : User가 ADMIN 권한에 접근 시도");

        response.setStatus(HttpServletResponse.SC_FORBIDDEN);

        Map<String, String> map = new HashMap<>();
        map.put("errortype", "Forbidden");
        map.put("code", "403");
        map.put("message", "허용하지 않는 권한에 접근하였습니다");

        response.getWriter().write(objectMapper.writeValueAsString(map));
    }
}
CustomAccessDeniedHandlerは、他のアクセス権限を含むHTTP応答を記述することができる.
次の文章では
内容がもっと長くなる前に、少し休んでから行きます.