首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >HttpServletResponse .sendError丢失CSRF令牌时返回空响应体

HttpServletResponse .sendError丢失CSRF令牌时返回空响应体
EN

Stack Overflow用户
提问于 2021-07-11 00:02:44
回答 1查看 839关注 0票数 1

我在配置中启用了CSRF,当我尝试在头或cookie中没有CSRF令牌的情况下向经过身份验证的端点发出POST请求时(第一个请求),Spring返回一个带有状态代码但没有响应体的错误响应(标头内容长度为0)。我在我的一个项目中遇到了这个问题,但是我尝试用一个更简单的设置来再现这种行为。

HelloController.java

代码语言:javascript
运行
复制
@RestController
public class HelloController {

  @PostMapping("/hello/")
  public String hello() {
    return "Hello World";
  }
}

SecurityConfig.java

代码语言:javascript
运行
复制
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  private final CustomAccessDeniedHandler customAccessDeniedHandler;

  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
      .anyRequest().authenticated();

    http.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler);
  }
}

CustomAccessDeniedHandler.java

代码语言:javascript
运行
复制
@Component
@Slf4j
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
  @Override public void handle(HttpServletRequest request, HttpServletResponse response,
                               AccessDeniedException accessDeniedException) throws IOException, ServletException {
    String errorMessage = accessDeniedException.getMessage();
    log.error("Access Denied - {}", errorMessage);
    response.sendError(HttpStatus.FORBIDDEN.value(), errorMessage);
  }
}

我知道,使用此设置,CSRF默认启用。我还定制了AccessDeniedHandler,因为我希望Spring在按预期工作时提供更具体的错误消息。当我使用curl -i -X POST http://localhost:8080/hello/时,Spring返回带有空响应的HTTP1.1 403。但是,如果删除http.authorizeRequests().anyRequest().authenticated();中的行SecurityConfig并启动上面相同的请求,就会出现类似于正常行为的错误消息。

代码语言:javascript
运行
复制
{
  "timestamp":"2021-07-10T23:06:28.172+00:00",
  "status":403,
  "error":"Forbidden",
  "message":"Could not verify the provided CSRF token because your session was not found.",
  "path":"/hello/"
}

我已经搜索过类似的问题,但是没有人回答为什么当response.sendError()存在时,.anyRequest().authenticated()会丢失CSRF令牌,为什么.anyRequest().authenticated()不能工作。解决方法似乎是使用response.setStatus()和response.getWriter().write()从头构建错误消息。这是一种预期的行为还是我遗漏了什么?

更新调试日志

代码语言:javascript
运行
复制
2021-07-10 17:52:23.933 DEBUG 24250 --- [nio-8080-exec-1] org.apache.tomcat.util.http.Parameters   : Set query string encoding to UTF-8
2021-07-10 17:52:23.939 DEBUG 24250 --- [nio-8080-exec-1] o.a.c.authenticator.AuthenticatorBase    : Security checking request POST /hello/
2021-07-10 17:52:23.939 DEBUG 24250 --- [nio-8080-exec-1] org.apache.catalina.realm.RealmBase      :   No applicable constraints defined
2021-07-10 17:52:23.944 DEBUG 24250 --- [nio-8080-exec-1] o.a.c.a.jaspic.AuthConfigFactoryImpl     : Loading persistent provider registrations from [/tmp/tomcat.8080.144327633803357340/conf/jaspic-providers.xml]
2021-07-10 17:52:23.945 DEBUG 24250 --- [nio-8080-exec-1] o.a.c.authenticator.AuthenticatorBase    : Not subject to any constraint
2021-07-10 17:52:23.949  INFO 24250 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-07-10 17:52:23.949  INFO 24250 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-07-10 17:52:23.949 DEBUG 24250 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected StandardServletMultipartResolver
2021-07-10 17:52:23.950 DEBUG 24250 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected AcceptHeaderLocaleResolver
2021-07-10 17:52:23.950 DEBUG 24250 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected FixedThemeResolver
2021-07-10 17:52:23.951 DEBUG 24250 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@5acdab24
2021-07-10 17:52:23.951 DEBUG 24250 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.support.SessionFlashMapManager@589cd2b7
2021-07-10 17:52:23.952 DEBUG 24250 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2021-07-10 17:52:23.952  INFO 24250 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms
2021-07-10 17:52:23.967 DEBUG 24250 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing POST /hello/
2021-07-10 17:52:23.974 DEBUG 24250 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
2021-07-10 17:52:23.978 DEBUG 24250 --- [nio-8080-exec-1] org.apache.tomcat.util.http.Parameters   : Set encoding to UTF-8
2021-07-10 17:52:23.993 DEBUG 24250 --- [nio-8080-exec-1] o.s.security.web.csrf.CsrfFilter         : Invalid CSRF token found for http://localhost:8080/hello/
2021-07-10 17:52:23.994 ERROR 24250 --- [nio-8080-exec-1] i.l.s.CustomAccessDeniedHandler          : Access Denied - Could not verify the provided CSRF token because your session was not found.
2021-07-10 17:52:23.997 DEBUG 24250 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
2021-07-10 17:52:23.999 DEBUG 24250 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
2021-07-10 17:52:24.000 DEBUG 24250 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
2021-07-10 17:52:24.000 DEBUG 24250 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost]           : Processing ErrorPage[errorCode=0, location=/error]
2021-07-10 17:52:24.005 DEBUG 24250 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing POST /error
2021-07-10 17:52:24.005 DEBUG 24250 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
2021-07-10 17:52:24.008 DEBUG 24250 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2021-07-10 17:52:24.018 DEBUG 24250 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [POST /error] with attributes [authenticated]
2021-07-10 17:52:24.021 DEBUG 24250 --- [nio-8080-exec-1] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2021-07-10 17:52:24.021 DEBUG 24250 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
2021-07-10 17:52:24.021 DEBUG 24250 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
2021-07-10 17:52:24.021 DEBUG 24250 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
2021-07-10 17:52:24.022 DEBUG 24250 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    :  Disabling the response for further output
2021-07-10 17:52:24.027 DEBUG 24250 --- [nio-8080-exec-1] o.a.coyote.http11.Http11InputBuffer      : Before fill(): parsingHeader: [true], parsingRequestLine: [true], parsingRequestLinePhase: [0], parsingRequestLineStart: [0], byteBuffer.position(): [0], byteBuffer.limit(): [0], end: [85]
2021-07-10 17:52:24.028 DEBUG 24250 --- [nio-8080-exec-1] o.a.tomcat.util.net.SocketWrapperBase    : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@5287597f:org.apache.tomcat.util.net.NioChannel@7d5d9d3:java.nio.channels.SocketChannel[connected local=/127.0.0.1:8080 remote=/127.0.0.1:38824]], Read from buffer: [0]
2021-07-10 17:52:24.029 DEBUG 24250 --- [nio-8080-exec-1] o.apache.coyote.http11.Http11Processor   : Error parsing HTTP request header

java.io.EOFException: null
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1345) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1255) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:799) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:359) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:261) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]

2021-07-10 17:52:24.029 DEBUG 24250 --- [nio-8080-exec-1] o.apache.coyote.http11.Http11Processor   : Error state [CLOSE_CONNECTION_NOW] reported while processing request

java.io.EOFException: null
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1345) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1255) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:799) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:359) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:261) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.46.jar:9.0.46]
    at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]

2021-07-10 17:52:24.030 DEBUG 24250 --- [nio-8080-exec-1] o.apache.coyote.http11.Http11Processor   : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@5287597f:org.apache.tomcat.util.net.NioChannel@7d5d9d3:java.nio.channels.SocketChannel[connected local=/127.0.0.1:8080 remote=/127.0.0.1:38824]], Status in: [OPEN_READ], State out: [CLOSED]
2021-07-10 17:52:24.031 DEBUG 24250 --- [nio-8080-exec-1] o.apache.tomcat.util.threads.LimitLatch  : Counting down[http-nio-8080-exec-1] latch=1
2021-07-10 17:52:24.031 DEBUG 24250 --- [nio-8080-exec-1] org.apache.tomcat.util.net.NioEndpoint   : Calling [org.apache.tomcat.util.net.NioEndpoint@68245ebc].closeSocket([org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@5287597f:org.apache.tomcat.util.net.NioChannel@7d5d9d3:java.nio.channels.SocketChannel[connected local=/127.0.0.1:8080 remote=/127.0.0.1:38824]])
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-11 16:09:59

看看你给出的日志:

代码语言:javascript
运行
复制
o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [POST /error] with attributes [authenticated]

.anyRequest().authenticated()正在阻止对默认/error页面的访问。如果您的配置方式允许此特定路径,则它可以按您的预期进行处理。

您可以通过简单地添加以下内容来做到这一点:

代码语言:javascript
运行
复制
.antMatchers("/error").permitAll()

实际上,如果您声明要允许的urls列表并将其设置为antMatchers参数,则可以允许所有您想要的urls。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68332372

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档