【问题标题】:Spring creates session with every POST requestSpring 为每个 POST 请求创建会话
【发布时间】:2016-01-18 19:34:30
【问题描述】:

我的目标是创建无状态 API。

到目前为止,GET 请求工作正常,但每当发出 POST 时,它都会创建会话。配置有什么问题?

问题已更新(根据 cmets)删除启动器:

aplicationContext.xml 的一部分:

<!-- Spring 4.0 namespaces used. -->
<security:http realm="Protected API" use-expressions="true" auto-config="false" create-session="stateless" entry-point-ref="authenticationEntryPoint">
    <security:custom-filter ref="authenticationFilter" position="PRE_AUTH_FILTER"/>
    <security:intercept-url pattern="/**"/>
</security:http>

<security:authentication-manager alias="authenticationManager" />

web.xml的一部分:

<!-- Spring configuration loading. -->
<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<!-- Spring request dispatcher. -->
<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!-- Spring security filters. -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

无论端点是否有效,这是我在发出 POST 请求时得到的堆栈跟踪:

java.lang.RuntimeException: Session support is not enabled in appengine-web.xml.  To enable sessions, put <sessions-enabled>true</sessions-enabled> in that file.  Without it, getSession() is allowed, but manipulation of sessionattributes is not.
    at com.google.apphosting.utils.jetty.StubSessionManager$StubSession.throwException(StubSessionManager.java:77)
    at com.google.apphosting.utils.jetty.StubSessionManager$StubSession.setAttribute(StubSessionManager.java:65)
    at org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.saveToken(HttpSessionCsrfTokenRepository.java:65)
    at org.springframework.security.web.csrf.CsrfFilter$SaveOnAccessCsrfToken.saveTokenIfNecessary(CsrfFilter.java:227)
    at org.springframework.security.web.csrf.CsrfFilter$SaveOnAccessCsrfToken.getToken(CsrfFilter.java:185)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:104)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:127)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366)
    at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349)
    at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:98)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:502)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

我根本不希望应用程序使用会话。我以为 create-session="stateless" 应该使用 NullSecurityContextRepository 但根据堆栈跟踪 HttpSessionCsrfTokenRepository 改为使用。

这里是 Spring 依赖项:

compile "org.springframework:spring-webmvc:4.0.2.RELEASE"
compile "org.springframework.security:spring-security-web:4.0.2.RELEASE"
compile "org.springframework.security:spring-security-config:4.0.2.RELEASE"

【问题讨论】:

  • /** 的拦截 URL 怎么样?谁可以访问它,你没有指定。
  • 对于初学者,请停止两次加载所有内容。您对ContextLoaderListener 和DispatcherServlet 使用相同的xml,导致创建重复的bean,从而导致各种问题。您也在使用 Spring Boot,然后使用 spring-boot-starter-security。默认情况下由于启用了CSFR而导致的存储库将其禁用。另外我想知道你为什么使用 Spring Boot 并且仍然有一个 web.xml 你确定你没有干扰 Spring Boot 启动和你自己的配置。
  • @WeareBorg 我希望过滤器对所有路径都处于活动状态,但不强制执行身份验证。 @M.Deinum 我完全删除了引导启动器并将security:http 标签移动到applicationContext.xml。我这样做的原因是因为许多教程都使用相同的 XML。我虽然春天处理。改完之后,问题还是一样。
  • 您想过滤但不想强制执行身份验证...更令人困惑。无论如何,清理你的代码或从头开始。
  • @WeareBorg 我一定会把它清理干净。这是我第一次使用 Spring。一旦我对每个标签的作用有信心,我一定会清理它。对于身份验证部分,它并不是那么复杂。根据请求是否经过身份验证,端点返回不同的内容。 public-private 内容并不是一个罕见的概念。

标签: java spring google-app-engine session spring-security


【解决方案1】:

看起来是 CSRF 保护试图创建会话。对于无状态服务,禁用它:

<security:http create-session="stateless" ...>
  <security:csrf disabled="true"/>
  <!-- the rest same as before -->
</security:http>

【讨论】:

  • 即使这可以解决问题,我还是建议您先进行清理,然后再为主要帖子的作者进行进一步的任务(不回答)。
  • 这就是问题所在。 @M.Deinum 在他的 cmets 中提到了它,但我对 Spring 真的很陌生并且没有正确理解它。
猜你喜欢
  • 2017-09-17
  • 2018-08-08
  • 2021-06-15
  • 2016-08-07
  • 2011-05-15
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
  • 2016-05-21
相关资源
最近更新 更多