vue实现单点登录的N种方式

最近项目停工了 , RageFrame的学习暂时告一段落 , 这一篇给大家分享下有关单点登录的相关知识 , 并提供一些demo给大家参考 , 希望对想了解的朋友有一些帮助 。

vue实现单点登录的N种方式

文章插图
话不多说 , 先上原理(借鉴地址:https://www.jianshu.com/p/613e44d4a464)点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下 , 用户在一处登录后 , 就不用在其他系统中登录 , 也就是用户的一次登录能得到其他所有系统的信任 。单点登录在大型网站里使用得非常频繁 , 例如像阿里巴巴这样的网站 , 在网站的背后是成百上千的子系统 , 用户一次操作或交易可能涉及到几十个子系统的协作 , 如果每个子系统都需要用户认证 , 不仅用户会疯掉 , 各子系统也会为这种重复认证授权的逻辑搞疯掉 。实现单点登录说到底就是要解决如何产生和存储那个信任 , 再就是其他系统如何验证这个信任的有效性 , 因此要点也就以下两个:
  • 存储信任
  • 验证信任
如果一个系统做到了开头所讲的效果 , 也就算单点登录 , 单点登录有不同的实现方式 , 本文就列出我开发中所遇见过的实现方式 。
vue实现单点登录的N种方式

文章插图
方法一:以Cookie作为凭证媒介最简单的单点登录实现方式 , 是使用cookie作为媒介 , 存放用户凭证 。
用户登录父应用之后 , 应用返回一个加密的cookie , 当用户访问子应用的时候 , 携带上这个cookie , 授权应用解密cookie并进行校验 , 校验通过则登录当前用户 。
vue实现单点登录的N种方式

文章插图
Auth via cookie不难发现以上方式把信任存储在客户端的Cookie中 , 这种方式很容易令人质疑:
  • Cookie不安全
  • 不能跨域实现免登
对于第一个问题 , 通过加密Cookie可以保证安全性 , 当然这是在源代码不泄露的前提下 。如果Cookie的加密算法泄露 , 攻击者通过伪造Cookie则可以伪造特定用户身份 , 这是很危险的 。
对于第二个问题 , 更是硬伤 。
vue实现单点登录的N种方式

文章插图
方法二:通过JSONP实现对于跨域问题 , 可以使用JSONP实现 。
用户在父应用中登录后 , 跟Session匹配的Cookie会存到客户端中 , 当用户需要登录子应用的时候 , 授权应用访问父应用提供的JSONP接口 , 并在请求中带上父应用域名下的Cookie , 父应用接收到请求 , 验证用户的登录状态 , 返回加密的信息 , 子应用通过解析返回来的加密信息来验证用户 , 如果通过验证则登录用户 。
vue实现单点登录的N种方式

文章插图
Auth via jsonp这种方式虽然能解决跨域问题 , 但是安全性其实跟把信任存储到Cookie是差不多的 。如果一旦加密算法泄露了 , 攻击者可以在本地建立一个实现了登录接口的假冒父应用 , 通过绑定Host来把子应用发起的请求指向本地的假冒父应用 , 并作出回应 。
因为攻击者完全可以按照加密算法来伪造响应请求 , 子应用接收到这个响应之后一样可以通过验证 , 并且登录特定用户 。
vue实现单点登录的N种方式

文章插图
方法三:通过页面重定向的方式最后一种介绍的方式 , 是通过父应用和子应用来回重定向中进行通信 , 实现信息的安全传递 。
父应用提供一个GET方式的登录接口 , 用户通过子应用重定向连接的方式访问这个接口 , 如果用户还没有登录 , 则返回一个的登录页面 , 用户输入账号密码进行登录 。如果用户已经登录了 , 则生成加密的Token , 并且重定向到子应用提供的验证Token的接口 , 通过解密和校验之后 , 子应用登录当前用户 。
vue实现单点登录的N种方式

文章插图
Auth via redirect这种方式较前面两种方式 , 接解决了上面两种方法暴露出来的安全性问题和跨域的问题 , 但是并没有前面两种方式方便 。
安全与方便 , 本来就是一对矛盾 。
vue实现单点登录的N种方式

文章插图
方法四:使用独立登录系统一般说来 , 大型应用会把授权的逻辑与用户信息的相关逻辑独立成一个应用 , 称为用户中心 。
用户中心不处理业务逻辑 , 只是处理用户信息的管理以及授权给第三方应用 。第三方应用需要登录的时候 , 则把用户的登录请求转发给用户中心进行处理 , 用户处理完毕返回凭证 , 第三方应用验证凭证 , 通过后就登录用户 。 
vue实现单点登录的N种方式

文章插图
以上 , 就是我了解的单点登录的给个模式及原理 , 下面给大家上实战代码 , 这里我列举两种情况 , 分类给大家讲解和提供我对应的demo(以下理论参考https://www.cnblogs.com/tibos/p/5354000.html)环境1:a.xxx.com需要跟b.xxx.com实现跨域,这种比较简单,只需要设置cookie的域名关联域就可以了 cookie.Domain = "xxx.com",这样两个域名间的cookie就可以互相访问,实现跨域.demo地址展示:系统一:sso1.linheng.xyz系统二:sso2.linheng.xyzvue具体代码:先打入指令安装js-cookienpm i js-cookie -S然后写入登录页面<template><div class="hello"><h1>{{ msg }}</h1><button @click="handleLogin">点击登录</button><button @click="rethome">返回首页</button></div></template><script>import Cookies from 'js-cookie'export default {name: 'home',data () {return {msg: '系统一登录页面'}},methods: {handleLogin() {var token = this.randomString();Cookies.set('app.token',token, { expires: 1000, path: '/', domain: '.**.com' })//这里换你的网站根目录Cookies.set('app.loginname','系统一', { expires: 1000, path: '/', domain: '.**.com' })//这里换你的网站根目录this.$router.push("/");},rethome(){this.$router.push("/");},randomString(e) {e = e || 32;var t = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678",a = t.length,n = "";for (var i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a));return n} }}</script><!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>h1, h2 {font-weight: normal;}ul {list-style-type: none;padding: 0;}li {display: inline-block;margin: 0 10px;}a {color: #42b983;}</style>接下来是首页:<template><div class="hello"><h1>{{ msg }}</h1><h3>用户信息为:{{token}}</h3><h3>登录地点:{{loginname}}</h3><button @click="logout">登出</button></div></template><script>import Cookies from 'js-cookie'export default {name: 'home',data () {return {msg: '系统一主页面',token:'',loginname:''}},mounted(){const token = Cookies.get('app.token');this.token = token;const loginname = Cookies.get('app.loginname');this.loginname = loginname;console.log(token);if(!token){this.$router.push("/login");}},methods: {logout(){Cookies.set('app.token','', { expires: 1000, path: '/', domain: '.**.com' })//这里换你的网站根目录Cookies.set('app.loginname','', { expires: 1000, path: '/', domain: '.**.com' })//这里换你的网站根目录this.$router.go(0)} }}</script><!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>h1, h2 {font-weight: normal;}ul {list-style-type: none;padding: 0;}li {display: inline-block;margin: 0 10px;}a {color: #42b983;}</style>系统二的对应页面也只是把这两个页面弄过去 , 改下文字方便识别而已 。写到这里 , 大家对于这个的思路已经比较清晰了 , 如果需要优化 , 我这边建议大家把判断和获取的方法统一弄成控件 , 然后在router里进行操作 , 这样会更好 。 这里分享下我封好的控件demo , 点击这里查看文章环境2:a.aaa.com需要跟b.bbb.com实现跨域,这种不同域名的情况下,想要实现就必须换种方式了.这个我还没有写好demo , 这个给大家提供我找到的最靠谱的思路及demo
vue实现单点登录的N种方式

文章插图
在这里我将引入第三者,s.sss.com这个站点,就是某个浏览器同时打开了这3个站点,我们访问A站点,先判断自身是否登录,如果session为空,就重定向到S站点,判断S站点上面是否有cookie,如果S站点上面也没有cookie,则由S站点重定向到A站点的登录页. 这样我们就实现了第一步,S站做的的就是隐藏在幕后,子站先判断自己是否存在session,如果不存在,就重定向到主站S上面去验证.第二步,验证登录信息合法性.这里我引入token(令牌),网上有很多资料,描述token的传递,工作方式是这样,A登录成功,保存自身的session,重定向到S,S在自己站点保存一个session跟cookie,session保存token对象{tokenID,userName,startTime,endTime},cookie保存tokenID,tokenID是一个Guid,把token对象缓存在集合里面,另起一个线程,根据endTime(过期时间)来定期清理集合列表,重定向到A的时候再将tokenID传递过去,拿到tokenID后,进入验证环节,S站有提供一个接口,根据tokenID获取token对象,如果获取到对象,且没有失效,则tokenID合法,跳入index页面.情况2,A登录,直接打开B,这时候B自身没有session,会主动请求主站,主站会返回cookieID(S站存在客户端的cookie),这个时候再走验证环节,如果通过,则B根据token对象创建自身的session,再跳入index.在这里整个单点登录就已经成功了,接下来附上流程图:
vue实现单点登录的N种方式

文章插图
前面流程图,太丑了,这里补上一张,希望有所帮助.
vue实现单点登录的N种方式

文章插图
收集的demo源码:SSO单点登录说明:新建2个站点xxx-xxx.com(主站),yyy-yyy.com(子站),修改hosts文件,将这两个域名都指向127.0.0.1即可.
vue实现单点登录的N种方式

文章插图
如果对您有所帮助 , 欢迎您点个关注 , 我会定时更新技术文档 , 大家一起讨论学习 , 一起进步 。【vue实现单点登录的N种方式】
vue实现单点登录的N种方式

文章插图