SSO单点登录在web上的关键点 cookie跨域

概述

其实WEB单点登录的原理挺简单的,抛开那些复杂的概念,简单来讲讲如何实现一个最基本的单点登录

1.首先需要有两个程序 例如: http://www.site-a.com 我们简称A http://www.stie-b.com 我们简称B
2.A 和 B 在登录认证逻辑上(通常使用的是session技术)将登录验证数据单独存在第三方的存储结构中,例如 ,数据库或者内存缓存服务器 关于这方面技术请自行去寻找相关资料
3.用户在登录A站点的时候,创建登录信息,并存起来 然后留出一个接口 可以讲一个已经登录的标识传递给B站点页面上
4.用户在访问B的时候 javascript从B页面上获取到A的登录标识,将这个标识发动到B的程序后端查询用户是否在A上具有登录信息,如果存在则登录确认,直接跳过B站点的登录逻辑

那么在整个四步当中,其实最麻烦的是4,因为A和B的域名不同,在浏览器段往往不允许跨域传递数据

解决方案

利用B页面上的iframe分帧来从B站点页面跳转到A站点接口页面上,通过window.name进行跨域通信

具体实施

A:

1
2
3
4
5
6
7
8
9
10
<?php
//index.php 创建需要跨域的信息
setCookie('key','跨域的cookie内容');


<?php
//sso.php 接口
echo '<script>';
echo 'window.name ='.$_COOKIE['key'];
echo '</script>';

B站点页面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
function domainData(url, fn)
{
var isFirst = true;
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
var loadfn = function(){
if(isFirst){
iframe.contentWindow.location = 'http://www.site-b.com/null.html';
isFirst = false;
} else {
fn(iframe.contentWindow.name);
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
iframe.src = '';
iframe = null;
}
};
iframe.src = url;
if(iframe.attachEvent){
iframe.attachEvent('onload', loadfn);
} else {
iframe.onload = loadfn;
}

document.body.appendChild(iframe);
}
</script>

<script type="text/javascript">
domainData('http://www.site-a.com/sso.php', function(data){
alert(data);
});
</script>
</body>
</html>

同时要注意代码当中的http://www.site-b.com/null.html 要创建一个这样的空白页面 保证iframe的访问顺序是 B的null → A的sso.php 现在先访问A的index.php创建cookie,然后再访问B的页面就可以获取到cookie数据了,至于具体怎么实现后端逻辑,不在本文探讨之内