@ExceptionHandler を使用して Spring Security 認証例外を処理する 質問する

@ExceptionHandler を使用して Spring Security 認証例外を処理する 質問する

私は Spring MVC を使用して@ControllerAdvice@ExceptionHandlerREST API のすべての例外を処理しています。Web MVC コントローラーによってスローされた例外に対しては正常に機能しますが、コントローラー メソッドが呼び出される前に実行されるため、Spring Security カスタム フィルターによってスローされた例外に対しては機能しません。

トークンベースの認証を行うカスタム Spring セキュリティ フィルターがあります。

public class AegisAuthenticationFilter extends GenericFilterBean {

...

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        try {

            ...         
        } catch(AuthenticationException authenticationException) {

            SecurityContextHolder.clearContext();
            authenticationEntryPoint.commence(request, response, authenticationException);

        }

    }

}

このカスタム エントリ ポイントを使用すると、次のようになります。

@Component("restAuthenticationEntryPoint")
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint{

    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage());
    }

}

このクラスを使用して例外をグローバルに処理します。

@ControllerAdvice
public class RestEntityResponseExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler({ InvalidTokenException.class, AuthenticationException.class })
    @ResponseStatus(value = HttpStatus.UNAUTHORIZED)
    @ResponseBody
    public RestError handleAuthenticationException(Exception ex) {

        int errorCode = AegisErrorCode.GenericAuthenticationError;
        if(ex instanceof AegisException) {
            errorCode = ((AegisException)ex).getCode();
        }

        RestError re = new RestError(
            HttpStatus.UNAUTHORIZED,
            errorCode, 
            "...",
            ex.getMessage());

        return re;
    }
}

私がする必要があるのは、Spring Security の AuthenticationException に対しても詳細な JSON 本文を返すことです。Spring Security の AuthenticationEntryPoint と Spring MVC の @ExceptionHandler を連携させる方法はありますか?

私は Spring Security 3.1.4 と Spring MVC 3.2.4 を使用しています。

ベストアンサー1

わかりました。提案されたとおりに、AuthenticationEntryPoint から自分で json を書き込んでみましたが、うまくいきました。

テストのために、AutenticationEntryPointからresponse.sendErrorを削除して変更しました。

@Component("restAuthenticationEntryPoint")
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint{

    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException {
    
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getOutputStream().println("{ \"error\": \"" + authenticationException.getMessage() + "\" }");

    }
}

この方法では、Spring Security AuthenticationEntryPoint を使用している場合でも、401 不正コードとともにカスタム JSON データを送信できます。

明らかに、テスト目的で私が行ったように JSON を構築するのではなく、いくつかのクラス インスタンスをシリアル化します。

Spring Boot では、SecurityConfiguration ファイルの http.authenticationEntryPoint() 部分に追加する必要があります。

おすすめ記事