配置的authenticationEntryPoint对带凭证的permit() GET请求不生效
Spring Security自定义401响应在GET请求中不生效的原因
配置代码
@Override protected void configure(HttpSecurity httpSecurity) throws Exception { // @formatter:off httpSecurity .csrf() .disable() .authorizeRequests() .antMatchers(HttpMethod.GET).permitAll() .anyRequest() .authenticated() .and() .httpBasic() .and() .exceptionHandling() .authenticationEntryPoint(authenticationEntryPoint()); // @formatter:on } private static AuthenticationEntryPoint authenticationEntryPoint() { return (request, response, authException) -> { response.addHeader("WWW-Authenticate", "Basic realm=\"Realm\""); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setStatus(HttpStatus.UNAUTHORIZED.value()); String message = authException.getMessage(); if (request.getHeaders("Authorization").hasMoreElements()) { message += ". Wrong Authorization Key."; } else { message += ". Missing Authorization Key im Header."; } response.getWriter().format(""" { "errors":[{ "status": %d, "title": "%s", "detail": "%s" } ] } """, HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.name(), message ); }; }
现象对比
- 携带错误凭证的POST请求:返回自定义格式化401响应
{ "errors": [{ "status": 401, "title": "UNAUTHORIZED", "detail": "Full authentication is required to access this resource. Wrong Authorization Key." } ] } - 携带错误凭证的GET请求:返回Spring Boot默认格式401响应
{ "timestamp": "2023-04-18T17:07:35.663+00:00", "status": 401, "error": "Unauthorized", "path": "/xxx/1111" }
原因解析
核心问题出在permitAll()的配置逻辑和Spring Security异常处理的触发条件:
- POST请求场景:所有非GET请求被配置为
anyRequest().authenticated(),即必须通过认证才能访问。当携带错误凭证时,认证失败会触发authenticationEntryPoint(这个组件的作用就是处理"请求需要认证但用户未通过认证"的场景),因此返回你自定义的响应格式。 - GET请求场景:所有GET请求被设置为
permitAll(),意味着这类请求允许匿名访问,不需要强制认证。此时即使请求携带了错误的Authorization凭证,Spring Security在认证失败后,会认为用户可以以匿名身份继续访问,因此不会调用你自定义的authenticationEntryPoint。认证失败的异常会被Spring Boot默认的BasicErrorController捕获,返回框架自带的错误响应格式。
简单来说:自定义的认证入口点仅对必须认证的请求生效,而permitAll的GET请求不在这个范围内,所以错误凭证引发的异常会走默认处理流程。
内容的提问来源于stack exchange,提问作者emoleumassi
相关产品推荐
相关产品推荐

