@42withyou
2015-02-28T06:51:52.000000Z
字数 5077
阅读 539
文档
文档地址:https://www.zybuluo.com/42withyou/note/71092
| 版本号 | 内容 | 制定人 | 制定时间 |
|---|---|---|---|
| 1.0 | 根据服务接口需求撰写文档 | 叶科忠 | 2015.2.10 |
实现青基会下属网站一处登陆,其它接入SSO系统的网站都同步登陆。
登陆成功后,前台从单点登陆服务器(passport.cydf.org.cn)获取接入的应用列表,通过 jsonp ajax 实现跨域重定向,向各个应用传递加密后的登陆信息,各个应用响应请求,设置加密cookie。
之后,各应用即可通过解析 cookie 获取到登陆信息。
相关文件:(http://passport.cydf.org.cn/styles/js/cydf_sso.js)
通过 jsonp ajax 实现跨域重定向,参考 https://api.jquery.com/jQuery.ajax/
用jquery ajax发起一次异步请求,server返回302,如果重定后url的域名跟ajax请求的域名是同一个域名的话,浏览器会再发起一次重定向后的http请求,请求成功会调用ajax的success函数,如果重定向后url的域名跟ajax请求的域名不是同一个域名,也就是跨域重定向(跨域redirect),这个时候浏览器看到返回的response的Location跨域了就不会再发起请求,请求被拦截了,ajax请求失败会调用error方法。
普通的ajax请求不行,我们需要通过 jsonp 的方式,而且需要设置crossDomain:true。
相关文件 CydfSSO.class.php
该文件提供两个类 CydfSSOCipher 和 CydfSSO,前者提供加密,后者提供开发友好的接口。
// CydfSSOCipher// 使用 AES-256 / CBC / ZeroBytePadding encrypt 加密,即 CBC 模式的 AES256 用于加密// 参考 PHP 手册 http://php.net/manual/en/function.mcrypt-encrypt.phpfunction __construct($securekey); // 实例化,$securekey 接入SSO时提供public function encrypt($input); // 加密public function decrypt($input); // 解密
// CydfSSOfunction __construct($securekey); // 实例化,$securekey 接入SSO时提供public function getUidFromCookie($cookie); // 从 cookie 获取 UserGUIDpublic function getCookieFromUid($uid); // 从 UserGUID 获取 cookie
cydf_sso.js 执行 CydfSSO.login(_hellocydf);
通过Jquery.getJSON()方法发起 http://passport.qjh.com/index/hello?h=_hellocydf 请求,跨域获取需要跨域设置登陆cookie的应用列表,返回一个Json数据
jQuery181025357960700057447_1423724693878({"sso":["http:\/\/passport.qjh.com\/index\/set_cookie?t=http:\/\/jlxd.qjh.com\/sso\/login&h=86KdN6Q2Kmu7s0s%2Fl%2BOb42qGSDkUwMHc10ZEo1vGycmmrmrObTtPB7ZZ7y8IbQOObdNgF19gLmIhT2KeqHCIh8wVmlq2iDJ4qH%2B3FVOdx6M%3D&callback=?","http:\/\/passport.qjh.com\/index\/set_cookie?t=http:\/\/cart.q.com\/sso\/login&h=iNzlVBQP%2B%2F78Vg3RwyszA0Mf0JCy5ISgloIRmu6qHlnlybSMafQ9U5a%2BShfHJRcBZP%2Fd0ZJtVsMuYCAcBEvCyr817qI1teWEb0S7i2WsyZ0%3D&callback=?","http:\/\/passport.qjh.com\/index\/set_cookie?t=http:\/\/xszz.qjh.com\/sso\/login&h=UfVYrNqjLlRQ1bjDdMbWpJZvyyMWk4nUlRhjong4kyaSUpCCiB9Kef9DHAOZ5Y7j1inunsATEBCSMMSe8bcQTOTYjSgkIE7q1mZGY0TJVEs%3D&callback=?"],"status":"success"});
js遍历sso,通过jQuery.getJSON()方法对其中的每条数据发起跨域的jsonp请求,返回一个重定向的Response(302 Moved Temporarily),而且是跨域的重定向
// Qequest HeadersRequest URL:http://passport.qjh.com/index/set_cookie?t=http://jlxd.qjh.com/sso/login&h=86KdN6Q2Kmu7s0s%2Fl%2BOb42qGSDkUwMHc10ZEo1vGycmmrmrObTtPB7ZZ7y8IbQOObdNgF19gLmIhT2KeqHCIh8wVmlq2iDJ4qH%2B3FVOdx6M%3D&callback=jQuery181025357960700057447_1423724693878&_=1423724699024Request Method:GETStatus Code:302 Moved Temporarily// Response HeadersLocation:http://jlxd.qjh.com/sso/login?c=86KdN6Q2Kmu7s0s%2Fl%2BOb42qGSDkUwMHc10ZEo1vGycmmrmrObTtPB7ZZ7y8IbQOObdNgF19gLmIhT2KeqHCIh8wVmlq2iDJ4qH%2B3FVOdx6M%3D
由于发起的是跨域的jsonp请求,所以浏览器会根据返回的重定向url(Location)发起一次请求,也就是最后的跨域设置Cookie的请求
其中 http://jlxd.qjh.com/sso/login 接口由接入方实现
// Qequest HeadersRequest URL:http://jlxd.qjh.com/sso/login?c=86KdN6Q2Kmu7s0s%2Fl%2BOb42qGSDkUwMHc10ZEo1vGycmmrmrObTtPB7ZZ7y8IbQOObdNgF19gLmIhT2KeqHCIh8wVmlq2iDJ4qH%2B3FVOdx6M%3DRequest Method:GETStatus Code:200 OK// Response HeadersSet-Cookie:hellocydf=86KdN6Q2Kmu7s0s%2Fl%2BOb42qGSDkUwMHc10ZEo1vGycmmrmrObTtPB7ZZ7y8IbQOObdNgF19gLmIhT2KeqHCIh8wVmlq2iDJ4qH%2B3FVOdx6M%3D; path=/; domain=jlxd.qjh.com; httponly
应用接入SSO时,需实现 login,和 logout 接口,供 cydf_cart.js 跨域调用传递加密的登陆信息
public function login() {$c = I('c'); // 获取c参数if (!$c) {return false;}// 设置cookie,$this->_main_domain为应用域名,如: jlxd.cydf.org.cn// 为保证安全性,请将 cookie httponly 设置为 truesetcookie('hellocydf', $c, 0, '/', $this->_main_domain, false, true);}
http://jlxd.qjh.com/sso/logout
public function logout() {session('login_user', null); // 退出当前登陆用户session('hellocydf', null); // 其它相关变量清理,请按应用自己逻辑处理// 删除 hellocydf cookiesetcookie('hellocydf', null, 0, '/', $this->_main_domain);}
接入成功后,应用通过 hellocydf cookie。获取登陆信息
// 各应用自己的登陆逻辑public function logOn($user) {session("login_user", $user);$this->_SSOLogOn($user['UserGUID']);return true;}// SSO 登陆逻辑protected function _SSOLogOn($uid) {$CydfSSO = new CydfSSO(C('SSO_SECURITY_KEY')); // 通过 SECURITY_KEY 实例化 CydfSSO类$hellocydf = $CydfSSO->getCookieFromUid($uid); // 获取加密串// 通过一定方式将加密串传递到前台 _hellocydf js 变量session('hellocydf', $hellocydf);// 前台js: var _hellocydf = "{:urlencode(session('hellocydf'))}";}// 同 logout接口protected function _SSOLogOut() {session('hellocydf', null);session('hellocydf_logout', 1);setcookie('hellocydf', null, 0, '/', C('MAIN_DOMAIN'));// 前台js: var _hellocydf_logout = "{:Session::get('hellocydf_logout', true)}";}public function logOut(){session("login_user", null);$this->_SSOLogOut();}
各应用需负责在登陆和退出登陆后设置对应JS变量,触发cydf_sso.js完成相应操作。