免登
- 也就是用户在网站A已经登录,希望不必再重复登录过程,即可以登录状态访问网站B
- 这其实是一种“信任交换”,即用户已经取得了网站A的信任,希望以一种安全的方式也取得网站B的信任
- 从网站A免登到网站B的信任交换其实就是交换“登录cookie”, 很显然“交换登录cookie”只是“信任交换”的一种情形;从普遍意义上讲,用户在系统A和系统B之间做“信任交换”,其实可以交换任意“信任凭证”,他们的原理都是大同小异的
面临的问题及解决方案
想要安全地做“信任交换”,以从网站A免登到网站B举例,其实主要是要解决如下几个问题:
- 免登目标地址的合法性
- 在任何一次跳转的过程中防止参数被篡改
- 任何一次跳转链接都要具有短效性和一次性(除了最后一次跳往目标地址的跳转)
- 免登目标所接受的参数的合法性(如果有的话)
- 在任意一次跳转的前后相邻两次请求之间,保证客户端不被顶替(即请求间保证ip一致或设备指纹一致)
第一个问题,“免登目标地址的合法性”,这是需要网站A解决的;建议网站A建立一个“合法的免登目标地址”列表,用以检测用户发起的免登请求的目标地址是否合法
需要注意的是,一个“合法”的免登目标地址,不仅仅是域名合法就行了,也包括path部份;因为不排除会有人将用户骗至一个执行重要操作的目标url进行免登,比如”www.B.com/resetPassword.do”,这是应当避免的
一般来讲,免登的目标地址应该是一个“无副作用”,无任何额外操作的类似于“主页”的地方,这样能杜绝上述情况发生
第二个问题,“在任何一次跳转的过程中防止参数被篡改”,这显然是必要的;从http跳转这种行为本身来讲,每一次跳转,服务器端都失去一次对该请求行为的控制,客户端想要更改跳转请求的任何属性都轻而易举
可以采用”数字签名”技术防止这种篡改;需要考虑的是,哪些数据需要被签名?这取决于该免登需求“在意”哪些数据被更改,一般来讲,都会对请求参数进行签名,当然其它数据,如path也可以被包含在内,如果path带有业务信息的话
由网站A负责加签,等请求经由客户端,在转发到网站B时,网站B会对请求进行验签; 这需要网站A和网站B事先约定好加签验签的密钥,一般来讲,对称的密钥串已经足够安全,只要密钥不被泄漏
另外,如果需要确保每次跳转后,访问服务器的仍是同一个客户端,那么这个签名步骤也可将客户端的ip地址或“设备指纹”等数据一并加签,以便验证请求在跳转过程中是否被劫持;不过这么做的风险是,并不仅仅只有被劫持的情况才会在跳转过程中改变客户端的ip,也可能是其它正常情况,比如A、B网站之间不同的网络架构造成的获取客户端ip地址误差等等,需三思而后行
第三个问题,“任何一次跳转链接都要具有短效性和一次性”,这也是显而易见的,否则客户端或搜索引擎只要将某个跳转中间阶段的url给收录下来,那么就随时可以免登了;有不少实力雄厚的大网站都出过这样的问题
这个问题可以通过“一次性令牌”方案简单解决,也就是说,跳转之前生成一个唯一的、一次性的、短期时效性的一个“令牌”,跳转到目标网站后在验证、作废该令牌
至于是网站A还是网站B负责生成这个令牌,其实无所谓,只要保证令牌的生成过程是私密的就行了:
- 若网站A生成令牌,则直接将该令牌放入跳转请求中,客户端跳转到网站B后,由网站B调用网站A暴露的令牌验证接口(比如http形式的接口)验证并作废该令牌
- 若网站B生成令牌,则跳转前网站A调用网站B的服务请求该令牌(注意该请求过程必须私密,一般不走http接口,若要走也需要有保密手段),跳转后由网站B验证并作废该令牌
上述两种策略都可以,但看起来显然由跳转发起方来做令牌的生成和提供验证接口比较好,这样省去远程调用令牌生成接口的麻烦
注意,最后一次跳转,也就是跳转到最终目标页面的那次跳转,由于有登录验证,因此不需要一次性令牌验证了,但仍然需要签名验证(如果带有业务参数的话)
第四个问题,“免登目标所接受的参数的合法性”;一般来讲,免登目标url是不建议带有参数的,但如果一定要带,那么是必需要网站B验证这些参数的业务合法性,以免恶意用户从一开始就传送一些非法参数过来
第五个问题,在多次跳转请求间“保证客户端不被顶替”,这个听起来概念复杂,但实现起来挺简单:只要在加签、验签的时候把客户端ip也算在里面就行了,当然如果网站已经实现了“设备指纹”技术那就更好了,这个问题就转化为:“多次请求跳转期间,通过签名、验签保证客户端设备指纹不被篡改”
解决好了上述几个问题,也就是几次跳转,写好cookie,最终跳到目标页面上的事情了。
综上,一个典型的,由网站A免登到网站B,其跳转执行流程如下: