httpservletresponse.senderror在缺少csrf令牌时返回空的响应正文

pgky5nke  于 2021-09-29  发布在  Java
关注(0)|答案(1)|浏览(422)

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

@RestController
public class HelloController {

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

securityconfig.java

@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

@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返回http/1.1403,响应为空。但是,如果我删除该行 http.authorizeRequests().anyRequest().authenticated(); 在securityconfig中,启动上面相同的请求时,会出现与正常行为类似的错误消息。

{
  "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令牌的情况。解决方法似乎是使用response.setstatus()和response.getwriter().write()从头构建错误消息。这是一种预期的行为还是我遗漏了什么?
更新调试日志

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]])
izj3ouym

izj3ouym1#

请查看您提供的日志:

o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [POST /error] with attributes [authenticated]

这个 .anyRequest().authenticated() 正在阻止对默认值的访问 /error 页如果您以允许此特定路径的方式进行配置,则它可以按预期进行处理。
您只需添加以下内容即可完成此操作:

.antMatchers("/error").permitAll()

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

相关问题