一步一步实现跨项目单点登录(SSO)

随着企业信息化建设的不断深入,各个业务系统之间的交互和整合变得尤为重要。单点登录(Single Sign-On,简称SSO)作为一种身份验证和授权机制,能够实现在多个应用系统中,用户只需一次登录,即可访问所有相互信任的应用系统,从而极大地提高了用户体验和系统安全性。本文将详细介绍跨项目单点登录的实现过程,并附带实际例子进行说明。

一、跨项目单点登录的实现原理

跨项目单点登录的实现主要依赖于以下几个关键点:

  1. Token:用户的身份凭证。
  2. 跨登录项目:需要集成单点登录功能的应用系统,能够接收并验证认证令牌,从而允许用户访问系统资源。
  3. Token存储与传递Token需要在用户与应用系统之间安全地存储和传递。

二、跨项目单点登录的实现步骤JWT

  1. 用户访问应用系统A,触发路由拦截。
  2. 应用系统A检查用户是否已持有有效的Token,如未持有,则重定向用户到登录界面进行登录。
  3. 用户在登录界面输入用户名和密码进行登录。
  4. 后端验证用户身份,如验证通过,则生成Token,并返回给应用系统A。
  5. 应用系统A接收到Token后,将其存储起来(如存储在浏览器的缓存中),并允许用户访问系统资源。
  6. 当用户需要访问其他应用系统B时,应用系统B同样会检查用户是否持有有效的Token。由于用户之前已在系统A登录过,因此可以直接从令牌存储中获取认证令牌,无需再次登录。

注意:如果未对浏览器缓存做缓存策略处理的话,默认策略理论上是拿不到不同端口不同域的缓存的,浏览器存储默认会加上域、端口作为缓存隔离的标准。

这时我们就需要通过单点时把token+特定条件进行二次加密去跟后端互通。(URL携带)

三、实战例子

后端是基于OAuth 2.0协议生成的Token。

前端以SM2加密必要信息为例,介绍跨项目单点登录的具体实现。

我们具体介绍前端的业务流程:

假设我们有两个项目:项目A(Web应用)和项目B(移动应用),它们需要实现跨项目的单点登录功能。

项目A集成单点登录

  1. 输入账号密码登录项目A,得到登录成功的Token令牌,并存储至缓存。
  2. 点击跳转项目B,跳转时发起一个获取SM2公钥并且返回特定的唯一令牌。
handleSsoLogin() {
      const token = getToken() // 获取cookies上的token

      getOAuthToken(token)
        .then(res => {
          const { authToken, publicKey } = res.data.content

          const auth = doEncrypt(`${authToken}${token}`, publicKey)

          const url = `xxxx/xxxx/xxxx?auth=${auth}`

          // 根据这个url进行单点跳转,并携带特殊令牌
        })
    },

具体 doEncrypt的实现可以看我这篇文章:前端如何用密文跟后端互通?原来那么简单!

项目B集成单点登录

  1. 发生跳转时进入路由拦截。
  2. 监听是否存在query,并且存在auth属性。
  3. 处理auth字段,发送后端解密并认证返回token。
 handleAuthSso() {
      const auth = getUrlKey('auth') // 根据Key获取Url上的参数

      if(auth) {
        
        validateSsoToken(auth)
          .thne(res => {
            const token = res.data.content

            if(token) {
              setToken(token) // set到浏览器缓存

              next() // 继续跳转目标页面
            } else {
              // 校验失败,请检查是否是加密错误或者是token失效
            }
          })
      }
    }

具体getUrlKey用了第三方库js-hodgepodge根据所传的key获取URL上的参数。1.3.X之后版本更名为getQueryByKey

源码如下:

const getUrlKey = 
  <T extends string>(name: T): string | null | undefined => 
    decodeURIComponent(
      (
        (new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ""])[1] as any)
          .replace(/\+/g, '%20')
    ) || null

项目B单点回项目A也是相同流程。

通过上述步骤,我们实现了基于OAuth 2.0和JWT的跨项目单点登录功能。前端应用通过存储和传递JWT,实现了用户在多个项目间的无缝切换和自动登录。同时,后端服务器对JWT的验证确保了用户身份的安全性和有效性。

原文链接:https://juejin.cn/post/7352817681896292364 作者:大码猴

(0)
上一篇 2024年4月2日 下午4:49
下一篇 2024年4月2日 下午4:59

相关推荐

发表回复

登录后才能评论