前提条件
1.有两个或者两个以上的web应用,这里以两个web应用为例
2.在满足某些条件时,需要从其中一个web应用处转发到另外的web应用
3.采用的转发技术是URL rewrite
4.使用的安全验证是Spring Security Framework
5.发送的request默认是需要做转发的request
问题描述
对项目进行如下操作,多次循环,顺序执行:
1.发送request请求,传入正确的账号密码,通过了验证,获取了正确的返回值
2.发送request请求,传入错误的账号和密码,未通过验证,获取了正确的返回值
3.发送request请求,传入错误的账号和正确的密码,未通过验证,获取了正确的返回值
4.发送request请求,传入正确的账号和错误的密码,有时能通过验证,获取了错误的返回值
具体分析
单个出错请求流程分析
发现:
1.在security chain 1 处加载了context,最后也在这里清除了context
2.在security chain 2 处直接使用了context,应该是通过url rewrite转发过来的
3.只在security chain 2处做了验证,但是验证结果有时正确,有时错误
怀疑验证结果和验证时使用的线程有关系
单个出错线程流程分析
流程图结合代码有以下结论:
1.这个场景存在两套web应用环境,所以清除web app 1的环境时不能影响到web app 2的环境
2.第一个web应用环境中,SecurityContextPersistenceFilter加载了一个context,同时设置了标记位FILTER_APPLIED的值,存储在第一个web应用的SecurityContextHolder中
3.通过RequestContextFilter和URL rewrite filter将第一个web应用加载的context和标志位FILTER_APPLIED传到第二个web应用
4.在第二个web应用环境中,在BasicAuthenticationFilter中:
a.如果之前没验证成功过,使用context进行验证,验证成功后生成验证成功标志信息isAuthenticated = true,该信息会被存储在第二个web应用的SecurityContextHolder中
b.如果之前验证成功过,使用存储的验证成功标志信息,这样就免除了验证操作
5.在拿到了请求结果后,会返回第一个web应用,清除加载第一个web应用的SecurityContextHolder的信息(这里就没法清除第二个web应用环境的相同信息)
所以,看到的现象就是: 如果一个线程在成功通过验证,那么在一段时间内,这个线程再被用到时就会无论密码正确还是错误,都能直接获取信息,给人一种绕过验证的假象;同时,如果一个线程一直未能成功验证,那就一直需要走账号密码验证。综合起来,就是有时是正确返回值,有时是错误返回值。
解决方式
只需要保证URL rewrite filter在security chain操作之前就可以了。 也就是彻底执行"单个请求流程",不在第一个web应用处走任何security chain,直接转发URL。
单个请求流程
也就是在一个请求中,只做一次验证操作,而且,如果是转发的URL,则在转发到最终的web应用处做验证。
<filter>
<filter-name>urlRewriting</filter-name>
<filter-class>UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>urlRewriting</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
如果URL rewrite配置不正确,可能会出现每次重启,URL rewrite filter和security chain加载乱序的问题。
最可靠的配置方式是在web.xml中进行设置。
参考资料
https://stackoverflow.com/questions/40674014/execute-servlet-filters-before-the-spring-security-filter-chain
https://cloud.tencent.com/developer/ask/118029
https://www.cnblogs.com/longfurcat/p/9417912.html