跨域单点登录系统的设计与实现
跨域单点登录系统的设计与实现
一、跨域单点登录系统整体设计
1. 系统架构
如上图所示:在系统存在一个认证中心以及多个站点。用户信息统一由认证中心管理,在其它子站的登录均会跳转到认证中心来登录。
2. 工作流程
单点登录系统的关键在于,当用户从一个子站登录后,它会在认证中心生成ticket标识,只要该标识存在就代表用户已经成功登陆了。每个子站在进入之前,无论本地ticket标识是否存在,均会去请求一次认证中心,要做的事情如下:如果子站ticket不存在,并不一定代表用户没有从别的子站登录,但是如果用户在别的子站登录过,则在认证中心一定会有ticket存在,则该次请求的目的就是去判断认证中心ticket是否存在,如果存在,则说明用户已经在别的子站登录了,要做的只是请求回来后在自己站点的cookie中种上ticket,如果不存在则说明用户根本没有登录,则直接跳转至登录页面即可;如果子站ticket存在,则它去认证中心请求的目的在于,如果认证中心ticket已经不存在了则说明用户已经退出了,则请求返回后需要将本地cookie中的ticket清掉,达到“一登全登,一退全退”的效果,如果认证中心ticket还存在,则需要验证该ticket的真伪,是不是该客户端的(需借助一些其他手段)。详细流程如下。
先假设用户从未登录过系统,当他访问A站点时,会去认证中心请求一次(jsonp跨域的请求),结果发现认证中心也没有ticket,则跳转至认证中心的登录页面,当用户在认证中心登录后,则认证中心会跳转至A站点,此时A站点还会去认证中心请求一次,而这次会拿到ticket返回,就将ticket种植在本站的cookie中,代表用户在本站已经登录了。
当用户此时又去访问B站点时,同样会先去认证中心请求一次,请求的结果发现ticket存在,则它将ticket也种在自己站点的cookie中,这样用户就不需登录就可以在B站点随意访问了。
当用户在B站点操作完退出时,会去认证中心请求一次,该次请求会将认证中心保存的ticket值清掉。当在别的站点操作,去认证中心请求时,发现ticket已经没有了,同时也会将自己站点的ticket清掉,这样,又会跳转至登录页面。
二、jsonp跨域脚本请求
跨域单点登录需要解决的一个技术点就是跨域的问题。利用jsonp可以解决该问题,在系统中需要做两件事。第一:在认证中心新建一个js文件(注意:该文件并不是认证中心使用的,而是给其它子站点做跨域访问使用的),实现ajax的jsonp请求,即在认证中心的js中,写一段ajax,它要去调一下本地的接口,以判断本地ticket是否存在。如果存在,在success的返回中,将ticket值种下。如果不存在,同样将ticket清掉(该操作是清除站点cookie,从而让用户退出)。第二:在系统中,其它各个子站点的头文件中,引用一段js,实现js远程加载,如下方式:
<script type=”text/javascript” src=”http://auth.gfly.com/js/RemotePlantCookies.js”></script>
这样,在子站点每次刷新时,都会加载一下认证中心的js文件,而该js文件是跨域的,在种cookie时,其实是种在各个子站点的。
jsonp跨域请求的示例如下:
$(document).ready(function(){ var res = $.ajax({ type:"get", dataType:"jsonp", url:"http://auth.gfly.com/index.php?r=user/user/getTicket", crossDomain:true, success:function(r) { var res = r; if(res.res == true) { var exp = new Date(); exp.setTime(exp.getTime() + 6 * 60 * 60 * 1000); document.cookie = "ticket="+res.token+";expires="+exp.toGMTString()+";path=/"; } else { var date = new Date(); date.setTime(date.getTime()-10000); document.cookie="ticket=000; expire="+date.toGMTString(); } }, error:function() { } }); });
三、安全说明
在cookie传递账号密码等信息是很危险的,虽然我们的ticket值是加密后的子串,但倘若别人截获了我的ticket,然后直接利用ticket给服务端发送请求信息,则它同样可以通过验证。基于此,稍微安全一点的方法是,登陆时,在认证中心端,同时将客户端的IP地址记录下来,在验证ticket的环节同时对比此时请求验证的客户端的IP地址是否与之前保存的IP地址一致,只有一致才可以通过验证,否则不予理睬。
注:与宏图联调单点登录系统完成。可喜可贺!!