单点登录 谁借莪1个温暖的怀抱¢ 2022-05-13 14:04 248阅读 0赞 # 初识单点登录 # 最初接触到单点登录要追溯到3年多以前了,那时候看到的只是passport,当时要做全国所有社区的登录,然后就照着内部文档写了代码,然后就接入了(这里要提一句是百度与腾讯一旦形成产品的技术项目,文档都很不错)然后就没有然后了...... 而知识的珍贵程度却是这样的: 知识珍贵度排名: 听过 < demo过 < 实际工作用过 < 实际工作中被坑过< 实际工作中被多次坑过或者深入研究总结过 所以,脱离工作去学习node可能收效不大,脱离项目去说前端优化可能不让人信服,不被ie坑也认识不到兼容,这个时候我们就要抓住工作中的点,一点点深入进去了,也许这一轮的瓶颈就自然而然的突破了呢,这是我最近的想法,也试着朝着相关的方向努力。 今天想要写passport事实上是工作中用到了这个点了,如果我就照着内部文档接入了似乎意义不大,所以我准备就着这个机会骚骚了解下原理,期望将他变成第一类知识沉淀。 **文中内容皆是自我总结或者查询,如果有误请您提出,文中代码比较简陋,仅帮助理解,勿用作实际项目** # 什么是单点登录 # 单点登录即single sign on,用以解决同一公司不同子产品之间身份认证问题,也就是说,a.baidu.com与b.baidu.com两个站点之间只需要登录一次即可。 一般来说单点登录实现原理为,首次访问一个站点时会被引导至登录页,用户登录验证通过,浏览器会存储一个关键key(一般采用cookie),用户访问其他系统时会带着这个key,服务器系统发现具有key标志后,会对其进行验证,如果通过便不需要再次登录了。 这里的关键为二,第一是key,其二为系统统一的认证机制,这当中key会有一系列规则保证登录的安全性,而统一的认证机制是单点登录的前提,key是由他提供出去,每次用户由以这个给出的key来这里验证,判断其有效性,这里的统一的验证平台便是passport,他负责着制作通行令牌,并且对其进行验证。 这里举个例子来说(有误请您指出): 子系统A统一到passport服务器鉴权,并且在passport处获取cookie,并将token加入url,跳转回子系统A 跳回子系统A后,使用token再次去passport验证(这里直接走webservice服务验证,不再跳转),验证通过便在A系统服务器生成session,以后访问子系统A,在有效时间内不到passport验证 进入子系统B,跳到passport鉴权,发现passport cookie已经存在(token),便直接跳回子系统B,url带有token值,使用token去验证流程与A一致 # 实现原理 # 以腾讯百度等公司产品来说,他们一般会有一个统一的域,比如: baidu.com => tieba.baidu.com、music.baidu.com、baike.baidu.com...... qq.com => feiji.qq.com、cd.qq.com、music.qq.com 这类共享一个主域,但是这类网站往往还会提供给第三方使用,比如腾讯会给tencent.com与jd.com使用,这个时候一些实现细节又不一样,但有一点是确定的: 单点登录要求共享一套账号体系,至少保存各个子系统的公共信息 用户登录态,我们存于session中,这个时候第一类站点的单点登录便比较简单,以百度为例,直接设置baike.baidu.com与tieba.baidu.com的session为cookie domain为baidu.com便可解决问题。 第二种情况比较普遍,便是music.qq.com与jd.com要实现单点登录,这个便完全跨域了,SSO的做法是将登录态保存至公用域,一般是passport.xx.com,比如百度为passport.baidu.com。 这个时候tieba.baidu.com或者music.baidu.com的授权检查与退出操作全部由SSO(passport.baidu.com)来进行 # 简单实现 # 单点登录的调用表现一般有两种: ① 跳转 ② 弹出层回调 当用户在子系统未登录时,便会携带相关参数,比如tieba.baidu.com去到SSO(passport.baidu.com)进行登录 登录成功SSO会生成ticket key并附加给源网址跳转回去,这个时候SSO上已经有用户的登录状态了,但是各个子系统仍然没有登录态,所以根据这个ticket设置各个子系统独立的登录态是需要的。 当在SSO验证结束后,会回到子系统,子系统会根据得到的ticket(SSO为此次登录生成的用户基本信息加密串)获取用户的基本信息,从而在本站设置登录态。 这里使用代码做一个说明,有2年没有写服务器端代码了,最后选来选去使用了node实现,才发现自己对node也很不熟悉啊!!! **passport的实现** 首先我们看看鉴权代码的实现 var path = require('path'); var express = require('express'); var router = express.Router(); //偷懒,将token数据写入文件 var fs = require('fs'); /* GET home page. */ router.get('/', function (req, res, next) { if (!req.query.from) { res.render('index', { title: '统一登录passport' }); return; } var from = req.query.from; var token = null; var cookieObj = {}; var token_path = path.resolve() + '/token_user.json'; req.headers.cookie && req.headers.cookie.split(';').forEach(function (Cookie) { var parts = Cookie.split('='); cookieObj[parts[0].trim()] = (parts[1] || '').trim(); }); token = cookieObj.token; //如果url带有token,则表明已经在passport鉴权过 if (token) { //存在token,则在内存中寻找之前与用户的映射关系 //异步的 fs.readFile(token_path, 'utf8', function (err, data) { if (err) throw err; if (!data) data = '{}'; data = JSON.parse(data); //如果存在标志,则验证通过 if (data[token]) { res.redirect('http://' + from + '?token=' + token); return; } //如果不存在便引导至登录页重新登录 res.redirect('/'); }); } else { res.render('index', { title: '统一登录passport' }); } }); router.post('/', function (req, res, next) { if (!req.query.from) return; var name = req.body.name; var pwd = req.body.password; var from = req.query.from; var token = new Date().getTime() + '_'; var cookieObj = {}; var token_path = path.resolve() + '/token_user.json'; //简单验证 if (name === pwd) { req.flash('success', '登录成功'); //passport生成用户凭证,并且生成令牌入cookie返回给子系统 token = token + name; res.setHeader("Set-Cookie", ['token=' + token]); //持久化,将token与用户的映射写入文件 fs.readFile(token_path, 'utf8', function (err, data) { if (err) throw err; if (!data) data = '{}'; data = JSON.parse(data); //以token为key data[token] = name; //存回去 fs.writeFile(token_path, JSON.stringify(data), function (err) { if (err) throw err; }); }); res.redirect('http://' + from + '?token=' + token); } else { console.log('登录失败'); } }); module.exports = router; 子系统A的实现 var express = require('express'); var router = express.Router(); var request = require('request'); /* GET home page. */ router.get('/', function (req, res, next) { var token = req.query.token; var userid = null; //如果本站已经存在凭证,便不需要去passport鉴权 if (req.session.user) { res.render('index', { title: '子产品-A-' + req.session.user, user: req.session.user }); return; } //如果没有本站信息,又没有token,便去passport登录鉴权 if (!token) { res.redirect('http://passport.com?from=a.com'); return; } //存在token的情况下,去passport主站检查该token对应用户是否存在, //存在并返回对应userid //这段代码是大坑!!!设置的代理request不起效,调了3小时 request( 'http://127.0.0.1:3000/check_token?token=' + token + '&t=' + new Date().getTime(), function (error, response, data) { if (!error && response.statusCode == 200) { data = JSON.parse(data); if (data.code == 0) { //这里userid需要通过一种算法由passport获取, //这里图方便直接操作token //因为token很容易伪造,所以需要去主战验证token的有效性, //一般通过webservers 这里验证就简单验证即可...... userid = data.userid; //有问题就继续登录 if (!userid) { res.redirect('http://passport.com?from=a.com'); return; } //取得userid后,系统便认为有权限去数据库根据用户id获取用户信息 //根据userid操作数据库流程省略...... // req.session.user = userid; res.render('index', { title: '子产品-A-' + userid, user: userid }); return; } else { //验证失败,跳转 res.redirect('http://passport.com?from=a.com'); } } else { res.redirect('http://passport.com?from=a.com'); return; } }); }); module.exports = router; **passport鉴权程序模拟** var express = require('express'); var router = express.Router(); var path = require('path'); var fs = require('fs'); /* GET users listing. */ router.get('/', function(req, res, next) { var token = req.query.token; var ret = {}; var token_path = path.resolve() + '/token_user.json'; ret.code = 1;//登录失败 if(!token) { res.json(ret); return; } //如果传递的token与cookie不等也认为是鉴权失败 // if(token != cookieObj['token']){ // res.json(ret); // return; // } fs.readFile(token_path, 'utf8', function (err, data) { if (err) throw err; if(!data) data = '{}'; data = JSON.parse(data); //如果存在标志,则验证通过,未考虑账号为0的情况 if(data[token]) { ret.code = 0;//登录成功 ret.userid = data[token]; } res.json(ret); }); }); module.exports = router; # 简单测试 # 测试之前需要设置host,这里继续采用fiddler神器帮助: ![222032422506488.png][] ![222032511717196.png][] 这边直接用node跑了3个服务器: ![222033243436229.png][] 然后打开浏览器输入a.com,直接跳到了,登录页: ![222034117185322.png][] 简单登录后(账号密码输入一致即可): ![222037159064884.png][] 这个时候直接进入子系统B: ![222038023751122.png][] 直接便登录了,说明方案大体上是可行的 # 结语 # 首先,这里的程序很简陋,很多问题,也没有做统一退出的处理,今天主要目的是了解单点登录,后面有实际工作再求深入。 这里附上源码,感兴趣的朋友看看吧[:http://files.cnblogs.com/files/yexiaochai/web.rar][http_files.cnblogs.com_files_yexiaochai_web.rar],注意依赖包 原文:http://www.cnblogs.com/yexiaochai/p/4422460.html [222032422506488.png]: /images/20220504/2e86a77e469f43bca2a65e5800ae4633.png [222032511717196.png]: /images/20220504/1e87362bfc8c403ca2ef15cd5620a5ab.png [222033243436229.png]: /images/20220504/f89d04e3711f4b0e8d2101f8ad7fd40f.png [222034117185322.png]: /images/20220504/23858b14010d40e2a43b2c9ce8ffced6.png [222037159064884.png]: /images/20220504/dda223423c9f402c9ac0c4b0cfe3cc08.png [222038023751122.png]: /images/20220504/efb1904ea89f4abbbe71ad56bc5ffbbf.png [http_files.cnblogs.com_files_yexiaochai_web.rar]: http://files.cnblogs.com/files/yexiaochai/web.rar
相关 循序渐进之单点登录(1)--单点登录原理 SSO 简单介绍 Single Sign On 在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。 ![在这里插入图片描述][watermark_t 拼搏现实的明天。/ 2023年06月27日 06:13/ 0 赞/ 56 阅读
相关 单点登录 官网 https://apereo.github.io/cas/4.2.x/planning/Architecture.html demo http://www.i 我不是女神ヾ/ 2022年11月03日 10:45/ 0 赞/ 204 阅读
相关 单点登录 业务需要,正在研究. 基本有以下三种方案 1.集中管理Session. 实现很简单,但缺点是 每次页面刷新都需要访问一次或两次 Session管理服务器, 水深无声/ 2022年09月19日 10:55/ 0 赞/ 211 阅读
相关 单点登录 1:什么事单点登录: SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主 男娘i/ 2022年07月13日 14:29/ 0 赞/ 205 阅读
相关 单点登录 一、单系统登录机制 1、http无状态协议 web应用采用browser/server架构,http作为通信协议。http是无状态协议,浏览器的每一次请求,服务 港控/mmm°/ 2022年06月11日 00:55/ 0 赞/ 217 阅读
相关 单点登录 项目分为三个模块 server client2 client1 server提供的接口 /user /tol 深藏阁楼爱情的钟/ 2022年05月24日 04:26/ 0 赞/ 248 阅读
相关 单点登录 1.3 CAS服务端部署 Cas服务端其实就是一个war包。 在资源\\cas\\source\\cas-server-4.0.0-release\\cas-serve 梦里梦外;/ 2022年05月16日 08:04/ 0 赞/ 269 阅读
相关 单点登录 初识单点登录 最初接触到单点登录要追溯到3年多以前了,那时候看到的只是passport,当时要做全国所有社区的登录,然后就照着内部文档写了代码,然后就接入了(这里要提一句 谁借莪1个温暖的怀抱¢/ 2022年05月13日 14:04/ 0 赞/ 249 阅读
相关 单点登录 以Cookie作为凭证媒介 最简单的单点登录实现方式,是使用cookie作为媒介,存放用户凭证。 用户登录父应用之后,应用返回一个加密的cookie,当用户访问子应用 £神魔★判官ぃ/ 2022年04月23日 13:18/ 0 赞/ 277 阅读
相关 单点登录 什么是单点登录? 单点登录(Single Sign On)说的简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其它系统中登录。也就是用户的一次登录能得到其它所有 布满荆棘的人生/ 2021年11月11日 04:10/ 0 赞/ 422 阅读
还没有评论,来说两句吧...