前后端分离单点登录SSO实现方案 淘宝、京东跨域获取Cookie、OAuth2、QQ客户端多种模式

  • 演示Demo站点 http://sso.exrick.cn
  • 开源版Github地址 https://github.com/Exrick/x-boot)
  • 开发文档 https://www.kancloud.cn/exrick/xboot/1009234
  • 获取完整版 http://xpay.exrick.cn/pay?xboot

演示Demo站点 http://sso.exrick.cn

前后端分离下单点登录实现

单点登录模式 优点 缺点
共享Cookie模式 简单方便,用户体验好 根域名需限制一致;Cookie可能不安全
OAuth2.0模式 灵活安全,不受站点限制 成本稍高,需独立的认证中心
跨域设置Cookie 用户体验好,不受站点限制 比较麻烦;Cookie可能不安全
客户端模式 用户体验好,不受站点限制 成本极高,依赖于用户本地安装客户端应用

共享Cookie模式【完整版】

  • 首先需进入“系统管理-系统配置”菜单中的“其他配置”设置你应用部署的一级域名,用户登录后将在该域名及子级域名下存储Cookie令牌accessToken用于其他站点获取接口,完整版用户详见xboot-sso项目。
  • 其他站点从Cookie中取出accessTokenCookies.get("accessToken")即可携带上accessToken请求其他接口,通常用于内部信任的站点
前后端分离单点登录SSO实现方案 淘宝、京东跨域获取Cookie、OAuth2、QQ客户端多种模式_第1张图片

OAuth2.0模式

认证中心

  • 即通过平台的独立统一认证站点完成身份认证,其他站点通过获取access_token完成授权以及之后的请求鉴权
    • XBoot统一认证地址: 运行前端,路由地址为/authorize,默认即 http://127.0.0.1:9999/authorize, 在线demo地址 http://xboot.exrick.cn/authorize

单点登录流程分析示例

两三句话就能讲明白的事情,网上的大多资料画再复杂的时序图也讲不清关键点

  • 站点1发现用户未登录时,跳转至认证中心
  • 认证中心发现用户未登录(Cookie中没有认证记录),显示认证中心的登录页面
  • 用户输入账号密码登录,认证成功后,前端记录认证信息保存后端返回的accessToken令牌(令牌中有对应的用户名username),后端Redis存入access_token对应信息,其key为username:站点1的clientId,返回站点1的access_token
  • 认证中心携带access_token跳转至站点1的回调地址
  • 站点1前端获取到access_token令牌,记录已登录状态,每次请求携带access_token

  • 站点2发现用户未登录时,跳转至认证中心
  • 认证中心前端判断已认证授权过:从前端Cookie中取出存储的accessToken(令牌中有对应的用户名username)
  • 认证中心调用已授权验证接口,先验证accessToken是否有效,若有效,则后端Redis存入新站点的access_token信息,其key为username:站点2的clientIdn,返回站点2的access_token
  • 认证中心携带access_token跳转至站点2的回调地址
  • 站点2前端获取到access_token令牌,记录已登录状态,每次请求携带access_token

注销流程分析示例

  • 任一站点用户退出登录,通过Redis失效所有以username开头的键值对即可

实现细节补充

  • 认证中心可通过clientId可获取站点的基本信息数据

退出登录接口

  • /xboot/oauth2/logout
    • 需要携带主站的accessToken,通常为信任的内部站点中使用,将删除失效当前用户登录的accessToken以及当前用户授权第三方应用的access_token

自动授权说明

  • 设置为自动授权后
    前后端分离单点登录SSO实现方案 淘宝、京东跨域获取Cookie、OAuth2、QQ客户端多种模式_第2张图片
  • 已认证登录的用户不会看到以下授权确认页面,将自动授权跳转。通常用于内部信任的站点以及单点登录的实现
    前后端分离单点登录SSO实现方案 淘宝、京东跨域获取Cookie、OAuth2、QQ客户端多种模式_第3张图片

跨域设置Cookie模式

淘宝、京东采用的方式

  • 完全跨域的情况下a.com是肯定不能直接在b.com下设置Cookie的,那怎么办?

    • 开放设置Cookie接口。b站点提供一个能在其站点下设置其Cookie的GET接口或JS脚本,供其他信任的站点如a站点调用
    • 用户先在a站点登录成功后,通知调用其他站点的接口,为其他站点设置上Cookie,实现单点登录
  • 核心技术点:利用GET请求加载静态资源无跨域限制(无同源限制),即JSONP的原理

    // a站点中将令牌给b站点
    <script type="text/javascript" src="http://b.com/setCookie?accessToken=令牌"/>
    
    // 动态创建
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'http://b.com/setCookie?accessToken=令牌';
    document.head.appendChild(script);
    
  • Github上也有一些JSONP的库,如 https://github.com/webmodules/jsonp

    $ npm install jsonp --save
    
    const jsonp = require('jsonp');
    
    jsonp('http://b.com/setCookie?accessToken=令牌', null, (err, data) => {
      if (err) {
        console.error(err.message);
      } else {
        console.log(data);
      }
    });
    
  • 退出登录同理,调用退出登录接口后端清除会话后,获得要清空的其他站点列表,依次用清除前端Cookie

  • 当然这中间还涉及很多安全校验,此处不再赘述

客户端单点登录模式

QQ客户端单点登录流程分析

  • 当本机电脑上启动了QQ客户端,再使用浏览器访问QQ相关站点,如QQ邮箱,会显示我们已经登录了的QQ账号信息提供快速登录
前后端分离单点登录SSO实现方案 淘宝、京东跨域获取Cookie、OAuth2、QQ客户端多种模式_第4张图片
  • 其关键原理为QQ客户端内置一了个小型的 Web Server监听了4301端口,并提供当前登录QQ信息的接口
  • 访问QQ邮箱登录页后会生成校验参数去访问这 Web Server提供的接口,实际地址为https://localhost.ptlogin2.qq.com:4301/,这个域名指向的是 127.0.0.1,可以解决Cookie跨域等权限问题
请求
GET https://localhost.ptlogin2.qq.com:4301/pt_get_uins?callback=ptui_getuins_CB&r=0.5658049977525998&pt_local_tk=-440325439
响应
var var_sso_uin_list=[{"uin":1012139570,"face_index":-1,"gender":0,"nickname":"Exrick","client_type":66818,"uin_flag":8388612,"account":1012139570}];ptui_getuins_CB(var_sso_uin_list);
  • 由于QQ有庞大的用户基群并且能保证大部分人安装使用QQ客户端,因此通过该方式为用户提供了便利

你可能感兴趣的:(Web-前端)