① 单点登录

1 概念

  • 单点登录SSO就是在一个多系统共存的环境下,用户的一次登录能得到其他系统的信任

2 使用独立登录系统实现单点登录

  • 用户中心:不处理业务逻辑,只处理用户信息的管理以及授权给第三方应用。第三方应用需要登录时,则要把用户的登录请求转发给用户中心处理,用户处理完返回凭证

  • 利用用户中心的 token 自动登陆 B项目且跳转到特定页面

2.1 从用户中心跳转到B项目的 /userCenterLogin 页面

2.2 修改B项目的 permission.js 文件

  • permission 主要负责全局路由守卫和登录判断
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' 
import 'nprogress/nprogress.css' 
import { getToken, getErrorCode } from '@/utils/auth' 
import getPageTitle from '@/utils/get-page-title'

// NProgress 是封装的进度条
NProgress.configure({ showSpinner: false }) 

// 路由白名单列表。不用登陆也可以访问 -- 增加userCenterLogin
const whiteList = ['/login', '/userCenterLogin']

router.beforeEach(async(to, from, next) => {
  // 请求路由时进度条开始
  NProgress.start()
  // 设置页面标题
  document.title = getPageTitle(to.meta.title)

  const hasToken = getToken()
  // 如果存在token,即存在已登录的令牌
  if (hasToken) {
    // 存在令牌时请求登陆,就让用户跳转到首页,避免重复登录
    if (to.path === '/login') {
      next({ path: '/' })
      // 关闭进度条
      NProgress.done()
    } else if (to.path === '/userCenterLogin') {
      next({ path: '/userCenterLogin' })
      NProgress.done()
    } else {
      // 有令牌跳转至其他页面,从vuex获取用户信息(有则说明不是第一次登录)
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        // 拿到信息后,跳转
        next()
      } else {
        try {
          // 没有用户信息,说明是第一次登录
          store.dispatch('user/getInfo').then(res => {
            // do sth...
            // 跳转
            next()
          }).catch(res => {
            // 如果出错,就去掉令牌,重新跳转至登录页
            store.dispatch('user/resetToken')
            next(`/login?redirect=${to.path}`)
          })
        } catch (error) {
          // 如果出错,就去掉令牌,重新跳转至登录页
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    // 没有token,即没有令牌
    var code = getErrorCode()
    // 判断用户请求的路径是否在白名单中
    if (whiteList.indexOf(to.path) !== -1) {
      // 不是-1就证明存在白名单,不管有无令牌,都直接去到白名单路由对应的页面
      next()
    } else {
      // 若不在白名单里,就跳转至登录页面
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  // 每次请求结束后都需要关闭进度条
  NProgress.done()
})

2.3 B项目的 userCenterLogin 页面

<template>
  <div />
</template>

<script>
export default {
  name: 'UserCenterLogin',
  created() {
    const ticket = window.location.href.split('?token=')[1]
    this.$store.dispatch('user/skipLogin', { ticket })
      .then(res => {
        this.$router.push({ path: '/' })
      })
      .catch(error => {
        console.log(error)
      })
  }
}
</script>

2.4 B项目的store写 skipLogin 方法

  import { skipLogin } from '@/api/user'
  skipLogin({ commit }, ticket) {
    return new Promise((resolve, reject) => {
      skipLogin(ticket).then(response => {
        // 处理登陆态
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

2.5 B项目的api定义 skipLogin 方法

// 跳转登录
export function skipLogin(data) {
  return request({
    url: common.CC_API + '/user/api/v2/sso/login',
    method: 'post',
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    data: qs.stringify(data)
  })
}
原文地址:https://www.cnblogs.com/pleaseAnswer/p/13570242.html