簡體   English   中英

Spring Security:如何更改響應的 HTTP 狀態?

[英]Spring Security: how to change HTTP Status for response?

如果授權失敗,我需要返回 HTTP 401 狀態。 我使用 Spring Security 和以下設置授權:

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                    .antMatcher(ADMIN_MATCHERS)
                    .authorizeRequests()
                    .antMatchers(ADMIN_MATCHERS)
                    .access("hasRole('ADMIN')")
                    .anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .usernameParameter(USERNAME)
                    .passwordParameter(PASSWORD)
                    .loginPage(ADMIN_LOGIN)
                    .permitAll()
                    .loginProcessingUrl("/admin/login/auth")
                    .failureHandler(customAuthFailureHandler)
                    .successHandler(successHandler())
                    .and()
                    .logout()
                    .logoutUrl("/admin/logout")
                    .logoutSuccessUrl(ADMIN_LOGIN)
                    .and()
                    .exceptionHandling()
                    .accessDeniedPage(ADMIN_LOGIN)
                    .and()
                    .csrf().disable()
                    .httpBasic();

我使用failureHandler()來處理它。

我寫了一個自定義處理程序:

@Component("customAuthFailureHandler")
public class CustomAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {
    private static final String ADMIN_LOGIN = "/admin/login";
    private static final Integer STATUS_UNAUTHORIZED = 401;
    private static final String RESPONSE_CODE_KEY = "Response-Code";
    private static final String RESPONSE_BAD_CREDENTIALS = "bad-credentials";

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.setStatus(STATUS_UNAUTHORIZED);
        response.addHeader(RESPONSE_CODE_KEY, RESPONSE_BAD_CREDENTIALS);
        getRedirectStrategy().sendRedirect(request, response, ADMIN_LOGIN);
    }
}

標頭返回 OK,但狀態為 302 而不是 401。

當您調用 sendError 時,它會將請求分派到 /error (它是 Spring Boot 注冊的錯誤處理代碼。但是,Spring Security 會攔截 /error 並看到您未通過身份驗證,從而將您重定向到登錄表單。

處理程序:

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
                                                                  final HttpHeaders headers,
                                                                  final HttpStatus status,
                                                                  final WebRequest request) {
        String error = "Malformed JSON request";
        return buildResponseEntity(new ApiError(HttpStatus.BAD_REQUEST, error, ex));
    }

    private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
        return new ResponseEntity<>(apiError, apiError.getStatus());
    }


    /**
     * Handle NoSuchElementException
     **/
    @ExceptionHandler(NoSuchElementException.class)
    protected ResponseEntity<Object> handleEntityNotFound(NoSuchElementException ex) {
        ApiError apiError = new ApiError(HttpStatus.NOT_FOUND);
        apiError.setMessage(apiError.getMessage());
        return buildResponseEntity(apiError);
    }

    @ExceptionHandler(Exception.class)
    public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
        ApiError apiError = new ApiError(HttpStatus.NOT_FOUND);
        //apiError.setMessage(Translator.toLocale(apiError.getMessage(), null));
        apiError.setMessage(ex.getMessage());
        return buildResponseEntity(apiError);
    }
}

錯誤:

public class ApiError {

    @Getter
    @Setter
    private HttpStatus status;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
    private LocalDateTime timestamp;

    @Setter
    @Getter
    private String message;

    @Setter
    @Getter
    private String debugMessage;

    @Setter
    @Getter
    private List<ApiValidationError> subErrors;

    private ApiError() {
        timestamp = LocalDateTime.now();
    }

    public ApiError(HttpStatus status) {
        this();
        this.status = status;
    }

    ApiError(HttpStatus status, Throwable ex) {
        this();
        this.status = status;
        this.message = "Unexpected error";
        this.debugMessage = ex.getLocalizedMessage();
    }

    public ApiError(HttpStatus status, String message, Throwable ex) {
        this();
        this.status = status;
        this.message = message;
        this.debugMessage = ex.getLocalizedMessage();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM