Vue使用OAuth2简化模式登录

Vue使用OAuth2简化模式登录

1. OAuth2简化模式概述

  OAuth2是一个基于令牌的安全框架,主要使用在第三方认证登录场景,关于OAuth2的相关知识可以参考——理解OAuth 2.0,这里暂不详细介绍。
  这里简单介绍一下简化模式,简化模式,可以通过客户端名称和一个redirect_uri,访问认证服务器,认证服务器认证之后,直接返回一个令牌,该令牌会在redirect_uri的后边使用#连接。例如:

// 请求url
GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
        &redirect_uri=http://localhost:9001/callback HTTP/1.1
    Host: server.example.com
 
// 认证之后,重定向结果:
HTTP/1.1 302 Found
Location: http://localhost:9001/callback#access_token=2YotnFZFEjr1zCsicMWpAA
          &state=xyz&token_type=example&expires_in=3600

  从上边的结果可以看出,简化模式最后的令牌信息,直接在url中展示,其中url的Hash部分包含了令牌信息,因此一般客户端可以从Hash中获取令牌信息,用于下一次访问。
  Spring Cloud微服务系统中,多个服务基本都需要进行身份认证,因此,可以使用OAuth2的认证授权方式,单独创建一个用户认证的微服务,解决整个系统的认证问题。如果只是微服务系统,我们可以使用密码模式,来做一个登陆页面,输入用户名和密码,可以看起来像一个完成的系统。
  但是,考虑到可能会和其他系统配合使用的情况,决定做成一个单点登陆的模式,所有的系统认证时,都去认证服务器登陆,认证服务器自己提供一个登陆界面。

2. Vue使用简化模式

  根据OAuth2的简化模式的相关特性,如果Vue使用该模式,可以将请求的redirect_uri设置为Vue的根目录,然后,根据当前请求路径的Hash获取令牌信息。
  实现方法,定义全局路由守卫:使用Vue的全局路由守卫,如果没有token的话,从请求中获取Hash,如果Hash中的token信息为空,则去认证服务器认证:

import router from './router'
import store from './store'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css'// progress bar style
import { getToken,setToken } from '@/utils/auth' // getToken from cookie
import {hasPermission} from '@/utils/hasPerm'
import {validateIsNull} from "./utils/validate";

NProgress.configure({showSpinner: false})

router.beforeEach((to, from, next) => {
  NProgress.start()
  // 获取保存的 token信息
  let token = getToken()
  let hasToken = token !== 'undefined' && token !== undefined && token !== null && token !== ''

  if (hasToken) {
    // 如果有token,再做权限判断等操作,这里暂时忽略
    ......
  } else {
  	// <1> 获取 location 中的hash信息,也就是 #后边的内容
    let tokenStr = location.hash
	// <2> 如果,hash中不包含令牌,去认证服务器认证
    if (tokenStr.indexOf('access_token') === -1) {
      window.location.href = process.env.AUTH_URI+ '/oauth/authorize?client_id=mobile-client&redirect_uri='+
        process.env.REDIRECT_URI+'&response_type=token'
    } else {
    // <3> 如果有令牌信息,处理 hash,获取其中的token,并保存
      let tokenMap = new Map()
      let tokenArray = tokenStr.substr(2).split('&')
      tokenArray.forEach(str => {
        let strArr = str.split('=')
        tokenMap.set(strArr[0], strArr[1])
      })
      setToken(tokenMap.get('access_token'))
      store.dispatch('SET_TOKEN', tokenMap.get('access_token'))
      // <4> 将路由再次跳转到主界面,主要是去掉hash中的内容
      router.push({path: '/'})

      NProgress.done()
    }

  }
})

router.afterEach(() => {
  NProgress.done()
})

假如Vue设置端口是9527,那么,认证之后请求的路径会是http://localhost:9527/#/access_token=......;
而我们知道vue-router默认使用 hash 模式,也会有一个#,因此

  • <1> 处,获取locationhash 内容。
  • <2> 处,需要使用window.location.href,让浏览器访问该路径,而认证服务器地址和前端项目地址可能生产和开发环境不同,为了避免发布修改代码,因此,我将其配置在了config目录下的文件中,暂时想到该方法。
  • <3> 处,根据获取的hash信息,截取其中的令牌信息,也就是access_token对应的值,并保存该值。
  • <4> 处,使用router.push({path: '/'})的主要原因在于,认证之后返回形如http://localhost:9527/#/access_token=......的路径,该路径会和vue的路由进行匹配,很明显不会配置改形式的路由,因此,使用此方式,将后边的信息给清除。
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值