结合浏览器证书的 SSO 实现

我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!

很多公司的办公电脑会与员工绑定,其中一种绑定手段就是在系统和浏览器里安装带有员工信息的安全证书。这样员工办公电脑也就代表了员工本人,这边介绍一种结合浏览器证书的 SSO 实现方案。

流程图

首先看下流程图;

流程介绍

访问页面

用户首先访问的肯定是前端页面,前端增加路由访问前拦截进行权限校验;

参考下面配置:

// router.config.js
// 下面的路由配置会在用户尝试访问routes中路由地址时,需要先走Routes;
{
    path: '/',
    Routes: ['src/pages/Authorized'],
    routes: [
    {
      path: '/XXX',
      name: 'XXX',
      icon: 'XXX',
      authority: 'XXX',
      component: './XXX',
    },
    ]
}
复制代码

获取权限

前端Authorized中进行权限判断;

componentDidMount()时尝试调用接口获取用户信息和菜单权限信息,如Promise.all([getCurrentUser(), getMenuList()])

这边用户信息和授权菜单信息是分开的接口,所以使用了Promise.all,也可以在一个接口中实现;

  • 用户已登录

用户已登录那么前端就已经有了用户Token,获取用户信息和菜单权限信息的网络请求中会携带上Token信息;

    • Token有效接口校验通过后,就可以正常返回用户信息和菜单权限信息,前端判断后访问目标页面;
    • Token失效接口校验不通过,返回Token失效,前端进行SSO;
  • 用户未登录

用户未登录,获取用户信息和菜单权限信息的网络请求中没有携带上Token信息,则接口校验不通过,返回鉴权失败,没有Token,前端进行SSO;

判断权限

前端的网络请求方法(一般统一封装处理)中判断返回鉴权失败需要SSO的约定Code后,尝试进行SSO;

// request.js
// 接口返回鉴权失败Code,进入SSO;
if (response.data.code === 499) {
    RedirectSSO();
}
复制代码

SSO 登陆

前端尝试访问SSO系统地址,并按其要求携带相关参数,进行SSO登录;

这里需要提前在SSO系统进行注册登记,获取相关参数;

一般需要携带SSO系统需要的参数,目标系统后端承接SSO结果的URL,以及前端承接SSO结果的URL(这里需要携带的其他参数与目标系统后端约定);

如:window.location.href=https://SSO_URL?SSO系统需要的参数&REDIRECT_URL=SSO系统校验后重定向到目标系统的地址+前端SSO承接地址

SSO 系统校验

前端访问SSO系统地址的网络请求中会携带浏览器上安装的员工个人安全证书信息,用于SSO系统的校验;

  • 如果校验成功,则携带校验成功的信息,重定向到目标系统的地址REDIRECT_URL;
  • 如果校验失败,则携带校验失败的信息,重定向到目标系统的地址REDIRECT_URL;

目标系统校验

目标系统收到SSO系统的校验结果后,使用结果信息向SSO系统查询校验结果,并换取员工信息,然后进行判断;

  • 如果成功,则根据SSO系统提供的员工信息,生成自己系统的Token,再重定向到前端SSO地址,并带上有效的Token和员工信息;
  • 如果失败,也重定向到前端SSO地址,但是不会携带Token;

前端SSO结果处理

前端SSO承接地址获取后端返回的Token和用户信息,进行判断;

  • 如果获取不到Token,则切换到登录页面;
  • 如果正确获取Token,则重新调用接口获取用户信息和菜单权限信息;

优化

  • 多环境配置

由于系统有产线环境、测试环境、开发环境,不同环境对应的SSO注册信息不同,需要分系统维护使用;

则可以在RedirectSSO()中根据process.env区分不同环境,使用不同环境配置;

  • 重定向丢失目标URL

由于SSO过程中存在多次重定向,URL携带参数存在丢失风险,所以可以将部分参数存储在前端缓存(如localStorage)中,待SSO有结果后再取出来使用;

Guess you like

Origin juejin.im/post/7068602406216728590
sso