下面给出了快速重现问题的完整代码和说明。
问题:
的自定义实现
HttpSession
将当前替换为已保存的. null
DefaultOAuth2RequestFactory
AuthorizationRequest
AuthorizationRequest
这会导致后续请求失败,因为/oauth/token
端点之前的 Spring Security 过滤器链中的CsrfFilter无法在/oauth/token
中找到 a与's进行比较。 session
Csrf token
null
session
request
Csrf token
错误期间的控制流程:
以下流程图说明了步骤 14和步骤 15以某种方式null
将HttpSession
. (或者可能与 a 不匹配JSESSIONID
。)第 14 步SYSO
开头的CustomOAuth2RequestFactory.java
A表明确实存在 a实际上包含正确的。然而,不知何故,当第 15 步触发客户端在url 上返回到端点 的调用时,它已经变成了。HttpSession
CsrfToken
HttpSession
null
localhost:8080/login
localhost:9999/oauth/token
HttpSessionSecurityContextRepository
在下面的调试日志中提到的每一行都添加了断点。(它位于 eclipse 项目的Maven Dependencies
文件夹中authserver
。)这些断点确认了在下面的流程图中发出HttpSession
最终null
请求的时间。/oauth/token
(流程图的左下角。) 这null
HttpSession
可能是由于自定义代码运行JSESSIONID
后保留在浏览器中的内容已过时。DefaultOAuth2RequestFactory
如何解决此问题,以便在流程图中的第 15 步结束后,在对端点HttpSession
的最终呼叫期间保持不变?/oauth/token
相关代码和日志:
的完整代码CustomOAuth2RequestFactory.java
可以通过单击此链接在文件共享站点上查看。 我们可以猜测这null
session
是由于 1.)JSESSIONID
中的代码没有在浏览器中更新CustomOAuth2RequestFactory
,或者 2.)HttpSession
实际被null
-ified。
步骤 15/oauth/token
之后调用的 Spring Boot 调试日志清楚地表明此时没有,可以读取如下: HttpSession
2016-05-30 15:33:42.630 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy : /oauth/token at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy : /oauth/token at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy : /oauth/token at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@2fe29f4b
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy : /oauth/token at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
2016-05-30 15:33:42.644 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.csrf.CsrfFilter : Invalid CSRF token found for http://localhost:9999/uaa/oauth/token
2016-05-30 15:33:42.644 DEBUG 13897 --- [io-9999-exec-10] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-05-30 15:33:42.644 DEBUG 13897 --- [io-9999-exec-10] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
在您的计算机上重现问题:
按照以下简单步骤,您只需几分钟即可在任何计算机上重现问题:
2.) 通过键入以下内容解压缩应用程序:tar -zxvf oauth2.tar(4).gz
authserver
3.)通过导航到oauth2/authserver
然后键入来启动应用程序mvn spring-boot:run
。
resource
4.)通过导航到oauth2/resource
然后键入来启动应用程序mvn spring-boot:run
ui
5.)通过导航到oauth2/ui
然后键入来启动应用程序mvn spring-boot:run
6.) 打开网络浏览器并导航到http : // localhost : 8080
7.) 点击Login
然后输入Frodo
用户名和MyRing
密码,点击提交。
8.) 输入5309
,Pin Code
然后单击提交。 这将触发上面显示的错误。
Spring Boot 调试日志将显示 A LOT of ,其中给出了流程图中显示的每个步骤SYSO
的变量值,例如XSRF-TOKEN
和HttpSession
。这SYSO
有助于对调试日志进行分段,以便它们更易于解释。所有这些SYSO
都是由其他类调用的一个类完成的,因此您可以操纵SYSO
-generating 类来更改控制流中各处的报告。SYSO
生成类的名称是TestHTTP
,它的源代码可以在同一个demo
包中找到。
使用调试器:
1.) 选择正在运行authserver
应用程序的终端窗口并键入Ctrl-C
以停止authserver
应用程序。
2.) 将三个应用程序(authserver
、、resource
和)作为现有的 maven 项目ui
导入到 eclipse 中。
3.) 在authserver
应用程序的 eclipse Project Explorer 中,单击展开Maven Dependencies
文件夹,然后在其中向下滚动以单击展开Spring-Security-web...
jar,如下图橙色圆圈所示。然后滚动查找并展开org.springframework.security.web.context
包。然后双击打开HttpSessionSecurityContextRepository
下面屏幕截图中以蓝色突出显示的类。向此类中的每一行添加断点。您可能希望对SecurityContextPersistenceFilter
同一包中的类执行相同的操作。 这些断点将使您能够查看 的值,该值HttpSession
当前在控制流结束之前变为null
,但需要具有可以映射到的有效值XSRF-TOKEN
才能解析此 OP。
4.) 在应用程序的demo
包中,在CustomOAuth2RequestFactory.java
. 然后Debug As... Spring Boot App
启动调试器。
5.) 然后重复上面的步骤 6 到 8。您可能希望在每次新尝试之前清除浏览器的缓存。您可能希望打开浏览器开发工具的“网络”选项卡。