[关闭]
@eric1989 2016-05-21T05:30:30.000000Z 字数 3412 阅读 808

单点登录方案


单点登录的作用

让用户实现单次登录,多个系统间无缝漫游的功能,即为单点登录。

单点登录的基本思路

单点登录最为核心的就是在用户端(基本上就是浏览器端)持有一个令牌Token(一个唯一性的字符串id),这个Token可以被写入到cookie中。这样在不同的系统中使用时都可以携带上这个token,系统的后台自动检测该token是否有效。有效的话,就可以到单点登录系统中获取用户信息,实际也就是相当于登录了。
大致的流程有两种情况。
直接将token写入cookie,并且访问资源

将token写入到cookie后重定向至原始资源

这两种流程其实差别不大。区别只是token是在什么时候被写入的而已。

单点登录面临的主要问题

单点登录中其实最主要的问题是在解决跨域上。从上面的基本思路中可以看到,单点登录在用户端的核心就是写入和读取cookie中的token值。但是如果用户在A域下面完成了单点登录,此时到B域的页面下面,由于浏览器是不允许读取跨域cookie,此时就需要再次登录。这就是单点系统中需要处理的跨域问题。

跨域问题解决手段

跨域的写cookie

通过页面上的javascript的跨域能力,可以在a域的页面中,放入一个b域的javascript请求,然后再这个请求中,完成对b域的cookie的写入。

P3P协议

上面的跨域写cookie有一个问题。如果是在ie浏览器下面,通过上面的这样的方式,对其他域进行cookie写入时被禁止。此时需要服务端在http的头部加入一个许可。这个许可就是P3P协议。有了这个许可,浏览器才会真正的将这个cookie写入到其他的域下。具体的代码如下

  1. response().addHeader("P3P", "CP=/"IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA/"");

跨域的读cookie

假设在a域的页面上,要读取一个b域的cookie。做法是通过在a域页面中的javascript连接中,放入一个对b域的read_cookie请求,而该请求后台可以返回一个javascript类型的响应,并且在这个响应中放入一些参数值,那么a域页面的其他地方就都可以读取到这个参数值,也就变相的在a域中读取到了b域的cookie了。

跨域的ajax请求

跨域的ajax请求主要是通过jsonp的方式实现。jquery有直接的支持,可以百度相关的资料。需要注意,jsonp的方式,需要后台返回的javascript代码而不是json字符串。

CORS方法跨域ajax请求

除了jsonp以外,还有一种更新的ajax协议可以支持跨域ajax。也就是CORS协议。但是这种要是需要浏览器能够支持(IE8以后,以及其他的浏览器都支持)。具体的做法就是通过普通的ajax请求向其他域发出请求,而服务端在响应的头部信息中加入Access-Control-Allow-Origin值来达到的。可以加入不同的网址,同构逗号区隔。这个值表示这些来源的网站可以进行ajax跨域访问本站资源。也可以使用*来表示支持任意来源的跨域ajax请求。

服务端功能

单点登录

对于服务端而言,基本要实现的功能包含两点,一是通过用户凭证进行登录并且给出授权token(该token是要写入到接入系统的域当中的),二是提供访问接口供验证授权token是否有效,以及通过该授权token换取用户信息。
登录
通过用户凭证进行登录。用户凭证本身可能有许多的形式,常见的有用户名和密码的组合,用户名和手机验证码的组合,单独的二维码等。不过一般来说,在一个系统中,可预期的组合是有限的。所以这部分的代码的扩展性到底要做的多强,需要根据业务而来。不需要完全的抽象。
在用户使用用户凭证登录成功的情况下,服务端除了给出登录成功的提示外,还应该生成一个全局唯一的token。该token应该写入所有的接入系统的域的cookie中,这样其他的接入系统就可以通过该token来完成免登陆的验证,进而达到不同子系统漫游的目的。

验证授权token
服务端应该有一个接口用来验证授权token是否有效,以及在有效的情况下返回该token对应的用户信息。在这个功能中有一点需要注意,通过token返回用户信息的时候需要考虑是否进行安全加密。以及如何避免用户信息被泄露。当然,如果只是非核心的信息,即使无安全防护也问题不大。

单点退出

单点退出的作用是让用户在任意一个系统完成退出后,在其他的系统也都达到退出的效果。从功能上说,包含以下三点

第三点需要展开说明一下。所有的接入系统应该实现一个消息接口或者提供一个退出的接口供sso系统来进行调用(不过这个调用通常是一个url连接,这个实现可以放在客户端的filter中实现)。
在客户端中可以让token和对应的session关联在一起。让某一个token失效,实际上就是让在接入系统中的session失效。当然,这只是一个思路,也有别的方案可以来达到这个目的。

自动登录功能

一般的网页登录都具备一个自动登录的功能。通常的做法就是在登录的时候提供一个勾选框,是否需要自动登录。如果勾选上的话,那么服务端在返回的时候需要写入一个自动登录的cookie。这个cookie可以用来完成以后的自动登录功能。
如果以后用户从第三方接入系统被重定向到sso系统尝试访问登录页面,那么如果检测到这个自动登录标识的存在,并且验证有效,那么服务端就不会返回需要输入用户名密码的登录页面。而是直接返回已经登录的提示页面。
通常来说,只要可以验证这个自动登录的cookie并且从这个cookie得到用户信息就可以完成自动登录。那么有的时候也会选择将用户的登录信息直接加密后保存到这个cookie值当中。具体做法如下

当用户在执行登录操作的时候,如果请求中携带了自动登录信息。则服务器上可以解密出用户名和密码的md5值的md5值,通过数据库比对就可以完成登录。
但是这个方案有个安全性上的问题。虽然cookie中的值本身不能反向解析出用户名和密码。但是这个cookie本身就是一个有效的自动登录标识。而cookie的截取是相对容易的。如果有第三方截取了这个cookie,不需要知道内容是什么,就可以使用这个cookie来完成在系统中的自动登录。此时除非修改密码,否则第三方就可以一直拿着这个cookie进行登录。
改进方案
那么有一种改进的方案就是将这个自动登录的标识的内容修改为一个无意义的全局唯一的字符串。并且每次登录后都会将原有的字符串失效,给出一个新的字符串。而用户在登录并且进行自动登录验证的时候,只需要验证这个字符串的存在与否即可。并且如果该自动登录标识被第三方窃取。只需要用户自己在系统上登录一次,就可以让窃取的自动登录标识无效化。这种方案在安全性上是有了保证。缺点就是只能在一台电脑上完成自动登录。

自动登录的login token和单点登录的sso token区别

自动登录的login token只保存在sso系统的域当中,作用是当用户访问sso的登录页面时,通过判断login token的有效性来完成自动登录,不需要用户输入用户名密码之类的用户凭证。
单点登录的sso token,应该存储在所有第三方接入的域当中。用于在接入系统中判断是否单点登录过。

客户端功能

sso的客户端其实主要就是一个过滤器的实现。大致上的思路如下

有几个需要实现的内容

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注