URL rewrite使用不当带来的问题


前提条件

1.有两个或者两个以上的web应用,这里以两个web应用为例
2.在满足某些条件时,需要从其中一个web应用处转发到另外的web应用
3.采用的转发技术是URL rewrite
4.使用的安全验证是Spring Security Framework
5.发送的request默认是需要做转发的request

问题描述

对项目进行如下操作,多次循环,顺序执行:
1.发送request请求,传入正确的账号密码,通过了验证,获取了正确的返回值
2.发送request请求,传入错误的账号和密码,未通过验证,获取了正确的返回值
3.发送request请求,传入错误的账号和正确的密码,未通过验证,获取了正确的返回值
4.发送request请求,传入正确的账号和错误的密码,有时能通过验证,获取了错误的返回值

客户端 服务器 正确的账号密码 正确的返回值 错误的账号密码 正确的返回值 错误的账号和正确的密码 正确的返回值 正确的账号和错误的密码 错误的返回值(有时) 客户端 服务器

具体分析

单个出错请求流程分析

客户端 web应用1 security chain 1 url rewrite filter web应用2 security chain 2 发送request请求 在web应用1上 load context 通过web应用1中的url rewrite filter 转发至web应用2 在web应用2上做authentication 清除load的context 返回信息 客户端 web应用1 security chain 1 url rewrite filter web应用2 security chain 2

发现:
1.在security chain 1 处加载了context,最后也在这里清除了context
2.在security chain 2 处直接使用了context,应该是通过url rewrite转发过来的
3.只在security chain 2处做了验证,但是验证结果有时正确,有时错误
怀疑验证结果和验证时使用的线程有关系

单个出错线程流程分析

客户端 tomcat thread web app 1 security url rewrite filter web app 2 security 第一次发送request请求 加载web应用1的context 通过url rewrite filter传输context至web应用2 使用web应用1的context,验证成功,生成验证信息存储 清除web应用1的context 返回信息 第二次发送request请求 加载web应用1的context 通过url rewrite filter传输context至web应用2 使用上次验证成功后存储的验证信息,判定验证通过 清除web应用1的context 返回信息 客户端 tomcat thread web app 1 security url rewrite filter web app 2 security

流程图结合代码有以下结论:
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。

单个请求流程

客户端 web应用1 url rewrite filter web应用2 security chain 发送request请求 直接通过web应用1中的url rewrite filter 转发至web应用2 在web应用2上做验证,然后获取相关信息 返回信息 客户端 web应用1 url rewrite filter web应用2 security chain

也就是在一个请求中,只做一次验证操作,而且,如果是转发的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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值