vue-admin:oauth2.0单点登录实现

背景:
现在有一个需求是客户要求使用oauth2.0方式的单点登录进入系统,原先我们都是使用cas方式的单点登录。这里整理下代码:

1.oauth2.0

分为4个步骤:

  1. 获取第三方token。
    为了安全性(不暴露第三方token和secretKey),c此处是后端对第三方提供的API进行处理,前端只去公司后端提供的接口中拿token。
  2. 拿到第三方token后,跳转到第三方认证平台。
  3. 跳转到第三方认证平台后,第三方平台在URL地址栏中携带ticket票据返回。
  4. 从地址栏中拿到票据,绑定用户信息。

拿到token后要把token保存到缓存中,在绑定用户信息时使用。

permission.js中代码实现:

if (window.g.OAUTH_URL) {
  if (window.g.OAUTH_URL && !window.location.search) {
    let oauthToken = ''
    getOauthToken().then((res) => {
      if (res.data.status) {
        // 1.获取token
        if (res.data.data.content) {
          oauthToken = res.data.data.content.token
          // 2.跳转到认证平台,不可以写在异步获取token的函数外面
          window.location.href = window.g.OAUTH_URL + `/unified_identity_logon/#/login?pcToken=${oauthToken}&applicationCode=${window.$oauthCmccr}`
          localStorage.setItem('Oauth_Token', oauthToken)
        }
      }
    })
  } else {
    // axios.get(`${window.g.OAUTH_URL}/unified_identity_logon/#/login?ticket=${window.location.search.split('=')[1]}`).then(res => {})
    // 3.认证平台跳回,并在地址栏包含ticket,获取ticket
    // const ticket = window.location.search.split('=')[1]
    var reg = new RegExp('ticket' + '=([^&]*)(&|$)', 'i') // /ticket=([^&]*)(&|$)/i
    var ticket = window.location.search.substr(1).match(reg)[1]
    // 4.获取用户信息
    const token = localStorage.getItem('Oauth_Token')
    getOauthUserInfo(ticket, token).then((res) => {
      if (res.data.status && res.data.content.hasOwnProperty('userId')) {
        const username = res.data.content.userId
        if (username) {
          // 5.绑定
          casBind(ticket, username).then(res => {
            if (res.data.code === 0) {
              axios.get(`${window.g.BASE_CCR}/oauth/token?client_id=xxxxx&client_secret=xxxxx&grant_type=password&username=${username}&password=${ticket}`).then(response => {
              //token和刷新token存到缓存中,各端保持登陆状态
                setToken(response.data.access_token, res.data.expires_in)
                setRefreshToken(response.data.refresh_token)
                autoGetToken(response.data.refresh_token)
                window.location.search = ''
                next('/')
              }).catch(() => {
                Message({
                  type: 'error',
                  message: '登录失败'
                })
                // 登陆失败再次跳到认证中心
                window.location.href = window.g.OAUTH_URL + `/unified_identity_logon/#/login?pcToken=${token}&applicationCode=${window.$oauthCmccr}`
              })
            }
          }).catch(() => {
            next()
          })
        } else {
          Message({
            type: 'error',
            message: '登录超时'
          })
          window.location.href = window.g.OAUTH_URL + `/unified_identity_logon/#/login?pcToken=${token}&applicationCode=${window.$oauthCmccr}`
        }
      }
    })
  }
}

在main.js中请求后端接口拿到登录地址。

axios.get(window.g.BASE_CCR + '/center/xxx/v1/xxxx/xxxxx').then(res => {
  if (res.data.code === 0) {
    var data = JSON.parse(res.data.data)
    // 应用码
    window.$oauthCmccr = data.userConfig.oauthCmccr
    // cas方式
    if (data.userConfig.authType === 'cas') {
      window.g.CAS_URL = data.userConfig.casLoginUrl || ''
      window.g.CAS_LOGOUT = data.userConfig.casLogout || ''
    } else {
      // oauth2.0方式
      window.g.OAUTH_URL = data.userConfig.oauthLoginUrl || ''
      // window.g.OAUTH_LOGOUT = data.userConfig.casLogout || ''
    }
  } else {
    Message({
      type: 'error',
      message: '配置信息获取失败'
    })
  }

你可能感兴趣的:(Vue)