Spring Security:如何更改HTTP状态以进行响应?

时间:2018-05-08 12:43:55

标签: java spring-security

如果授权不成功,我需要返回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。

2 个答案:

答案 0 :(得分:0)

当您调用sendError时,它将把请求分派到/ error(它是Spring Boot注册的错误处理代码。但是,Spring Security将截获/ error并看到您未通过身份验证,因此将您重定向到登录表单

答案 1 :(得分:0)

处理程序:

@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);
    }
}

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();
    }
}