vue中 给企业微信自建应用授权(静默授权,手动授权,扫码授权)

在web开发中,会遇到通过企业微信授权的形式进行免登录或快速登录的需求。

如果该应用是企业微信自建应用,那可以在管理平台获取到相应的appIdagentid等必要参数。

企业微信提供了OAuth的授权登录方式,可以让从企业微信终端打开的网页获取成员的身份信息,从而免去登录的环节。

现在已经搭建好vue的项目并且企业微信应用相关参数也已经获取到,那就开始吧。

一、静默授权与手动授权

  • 静默授权:用户点击链接后,页面直接302跳转至 redirect_uri?code=CODE&state=STATE
  • 手动授权:用户点击链接后,会弹出一个中间页,让用户选择是否授权,用户确认授权后再302跳转至 redirect_uri?code=CODE&state=STATE

构造网页授权链接

https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE&agentid=AGENTID#wechat_redirect

示例:

const redirectUrl = encodeURIComponent(`${window.location.origin}/callback`);  
const state = '123'; // 用于防止CSRF攻击,可以是任意字符串
const appId = 'your_app_id'; // 企业微信应用ID
const scope = 'snsapi_base'; // 授权类型,snsapi_base或snsapi_privateinfo
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`;
window.location.href = url;

此时会提示在企业微信环境中打开链接,页面将跳转至 redirect_uri?code=CODE&state=STATE,企业可根据code参数获得员工的userid。code长度最大为512字节。

 

接下来步入正题:在vue项目中配置。

其实vue项目中我们已经做过登录的路由守卫,那现在免登录其实就是对登录逻辑的调整,那就直接载permission.js中修改就行。

router.beforeEach中进行判断:

 1 router.beforeEach((to, from, next) => {
 2   const token = getToken() // token
 3   const redirectUrl = encodeURIComponent(`${window.location.origin}`) // 重定向url
 4   const appId = 'ww****123' // 企业微信ID
 5   const scope = 'snsapi_base' // 授权类型,snsapi_base(静默授权)或snsapi_privateinfo(手动授权)
 6   const urlState = '123' // 用于防止CSRF攻击,可以是任意字符串
 7   const agentid = '123***123' // 企业内应用id
 8   const openUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${urlState}&agentid=${agentid}#wechat_redirect`
 9   setTimeout(() => {
10     if (token) { // 已登录,有token
11       if (to.path === '/login') {
12         next({
13           path: '/'
14         })
15       } else {
16         next()
17       }
18     } else { // 没有token,去授权
19       window.location.href = openUrl
20     }
21   }, 0)
22 })

在 window.location.href = openUrl 后会重定向返回code和state,根据这两个字段来获取用户信息,所以得先判断我们的路由中是否带有这两个字段,如果有要先去除

 1 function delCodeandstate (to) {
 2   let path = ''
 3   for (const i in to.query) {
 4     if (i != 'code' && i != 'state') {
 5       path = path + '&' + i + '=' + to.query[i]
 6     }
 7   }
 8   path = path == '' ? '' : path.substring(1, path.length)
 9   path = path == '' ? '' : '/?' + path
10   return path
11 }

注意因为企业微信返回的code和state是固定的,所以避免判断出现混淆,我们在路由切换中避免使用code和state作为传参关键字,清除链接中的code和state避免页面反复跳转。

如果获取到code和state,还要和token一起作为判断条件,判断token是否存在并且是否过期等。

补全完整逻辑:

 1 import router from './router'
 2 import store from './store'
 3 
 4 import { getToken } from './auth'
 5 
 6 // 去除链接中的code和state
 7 function delCodeandstate (to) {
 8   let path = ''
 9   for (const i in to.query) {
10     if (i != 'code' && i != 'state') {
11       path = path + '&' + i + '=' + to.query[i]
12     }
13   }
14   path = path == '' ? '' : path.substring(1, path.length)
15   path = path == '' ? '' : '/?' + path
16   return path
17 }
18 router.beforeEach((to, from, next) => {
19   var fullPath = to.fullPath
20   // 判断是否存在code
21   if (fullPath.includes('code')) {
22     fullPath = delCodeandstate(to)
23   }
24   const token = getToken() // 获取token
25   const redirectUrl = encodeURIComponent(`${window.location.origin}`) // 授权登陆后的回调地址,需要进行encodeURIComponent处理
26   const appId = 'ww****123' // 企业微信ID
27   const scope = 'snsapi_base' // 授权类型,snsapi_base(静默授权)或snsapi_privateinfo(手动授权)
28   const urlState = '123' // 用于防止CSRF攻击,可以是任意字符串
29   const agentId = '123***123' // 企业内应用id
30   const openUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUrl}&response_type=code&scope=${scope}&state=${urlState}&agentid=${agentId}#wechat_redirect`
31   const code = to.query.code // 链接中code
32   const state = to.query.state // 链接中state
33   const whiteList = ['/login'] // 免登录白名单
34   let isCur = false // 是否免登录
35   setTimeout(() => {
36     // 判断白名单
37     for (const i of whiteList) {
38       if (to.path == i) {
39         isCur = true
40       }
41     }
42     if (isCur) {
43       next() // 白名单内不做登录判断,直接next
44     } else {
45       if (code && state && !token) {
46         // 获得授权后,不存在登录信息
47         const fd = {
48           code: code,
49           state: state
50         }
51         // 接口请求获取登录信息,根据自己逻辑配置
52         store.dispatch('WXCallback', fd).then((res) => {
53           next({
54             path: '/'
55           })
56         }).catch(() => {
57         })
58       } else if (token) {
59         // 已经存在登录信息,有token,判断token是否过期
60         store.dispatch('CheckToken').then((res) => {
61           // 判断token是否过期,以及token过期后清除token的操作可以在request的拦截中进行,也可以在CheckToken中进行
62           if (res.code == 200) {
63             // token未过期,直接登录
64             next({
65               path: '/'
66             })
67           } else if (res.code == 401) {
68             // token已过期,重新授权登录
69             window.location.href = openUrl
70           }
71         }).catch(() => {
72         })
73       } else { // 未登录,没有token,进行授权登录
74         window.location.href = openUrl
75       }
76     }
77   }, 0)
78 })

 

二、扫码授权

企业微信提供了OAuth的扫码登录授权方式,可以让企业的网站在浏览器内打开时,引导成员使用企业微信扫码登录授权,从而获取成员的身份信息,免去登录的环节。

 

构造独立窗口登录二维码

https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=CORPID&agentid=AGENTID&redirect_uri=REDIRECT_URI&state=STATE

代码逻辑与网页授权一直,只是授权链接不同:

 1 import router from './router'
 2 import store from './store'
 3 
 4 import { getToken } from './auth'
 5 
 6 // 去除链接中的code和state
 7 function delCodeandstate (to) {
 8   let path = ''
 9   for (const i in to.query) {
10     if (i != 'code' && i != 'state') {
11       path = path + '&' + i + '=' + to.query[i]
12     }
13   }
14   path = path == '' ? '' : path.substring(1, path.length)
15   path = path == '' ? '' : '/?' + path
16   return path
17 }
18 router.beforeEach((to, from, next) => {
19   var fullPath = to.fullPath
20   // 判断是否存在code
21   if (fullPath.includes('code')) {
22     fullPath = delCodeandstate(to)
23   }
24   const token = getToken() // 获取token
25   const redirectUrl = encodeURIComponent(`${window.location.origin}`) // 授权登陆后的回调地址,需要进行encodeURIComponent处理
26   const appId = 'ww****123' // 企业微信ID
27   const urlState = '123' // 用于防止CSRF攻击,可以是任意字符串
28   const agentId = '123***123' // 企业内应用id
29  const openUrl = `https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=${appId}&agentid=${agentId}&redirect_uri=${redirectUrl}&state=${urlState}`
30   const code = to.query.code // 链接中code
31   const state = to.query.state // 链接中state
32   const whiteList = ['/login'] // 免登录白名单
33   let isCur = false // 是否免登录
34   setTimeout(() => {
35     // 判断白名单
36     for (const i of whiteList) {
37       if (to.path == i) {
38         isCur = true
39       }
40     }
41     if (isCur) {
42       next() // 白名单内不做登录判断,直接next
43     } else {
44       if (code && state && !token) {
45         // 获得授权后,不存在登录信息
46         const fd = {
47           code: code,
48           state: state
49         }
50         // 接口请求获取登录信息,根据自己逻辑配置
51         store.dispatch('WXCallback', fd).then((res) => {
52           next({
53             path: '/'
54           })
55         }).catch(() => {
56         })
57       } else if (token) {
58         // 已经存在登录信息,有token,判断token是否过期
59         store.dispatch('CheckToken').then((res) => {
60           // 判断token是否过期,以及token过期后清除token的操作可以在request的拦截中进行,也可以在CheckToken中进行
61           if (res.code == 200) {
62             // token未过期,直接登录
63             next({
64               path: '/'
65             })
66           } else if (res.code == 401) {
67             // token已过期,重新授权登录
68             window.location.href = openUrl
69           }
70         }).catch(() => {
71         })
72       } else { // 未登录,没有token,进行授权登录
73         window.location.href = openUrl
74       }
75     }
76   }, 0)
77 })

 

注意:静默授权和扫码授权只能获取用户基本信息,若要用户敏感信息需要手动授权。

基本信息:用户id,座机号,姓名,别名

敏感信息:手机号,性别,邮箱,企业邮箱,头像url,个人二维码,地址

好了  到此就是关于静默授权、手动授权、扫码授权的相关操作。

 

posted @ 2023-03-15 19:31  涼皮Herr  阅读(5668)  评论(1编辑  收藏  举报