Uniapp在开发微信内H5页面微信授权功能时的案例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import qs from 'qs';
function authWechat(params, type=1) {
// 跳转到静默授权页
const redirect_uri = encodeURIComponent(process.env.WXAUTH_ORIGIN + '?' + qs.stringify(params));
const auth_type = type===1 ? 'snsapi_baseinfo' : 'snsapi_userinfo'
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${process.env.APP_ID}&redirect_uri=${redirect_uri}&response_type=code&scope=${auth_type}&state=STATE#wechat_redirect`;
location.href = url;
}
export default {
data(){
return {
options:{},
}
},
onLoad(options){
this.options = options;
},
methods:{
auth(){
authWechat({
origin: location.origin+location.pathname,
...this.options
})
}
}
}
|
1
2
3
4
|
location / {
rewrite (.*) $arg_origin permanent;
index index.html;
}
|
案例解读
先说一下以上案例在实际项目中将要执行的流程,
假设
- 当前打开页面地址为
a.com/pages/vip/vip?type=1&age=2
,
- 微信公众号中绑定的合法授权域名为
auth.com
那么页面在微信浏览器中的跳转踪迹为:
- 访问 a.com/pages/vip/vip?type=1&age=2
- 点击某个按钮后会跳转到
open.weixin.com/...redirect_uri=auth.com&origin=a.com/pages/vip/vip&type=1&age=2
- 微信静默(主动)授权后, 会访问
auth.com&origin=a.com/pages/vip/vip&type=1&age=2
, 但是被nginx拦截重定向到 a.com/pages/vip/vip&type=1&age=2
页面了
也就是说, 在这个过程中, 浏览器只进行了2次自动跳转
这里牵扯到两个重要的问题
- 微信授权中
redirect_uri
传参问题
- 是否允许用户在
auth.com
域名下操作业务问题
是否允许用户在auth.com
域名下操作业务
先说一下为什么我们要在nginx
中对访问auth.com
的页面重定向到最初的域名.
-
微信公众平台只允许绑定2个合法的授权域名, 也就是说 如果你有三个业务域名a.com, b.com, c.com
, 如果他们在授权后都停留到auth.com
下, 那auth.com
的虚拟主机应该绑定到哪个业务下呢 ( 当然了, 通过pathname来区分项目是可以区分项目的 )
-
实际业务中, 最好是把认证业务与普通业务分开处理, 所以最好是只把auth.com
当做一个中间平台, 只用来获取微信授权返回的code, 不要让用户在这个域名下处理实际业务.
-
所以, auth.com
获取到微信授权返回的code后, 自动跳转到原先的业务域名下即可
为什么要在nginx中对auth.com
做重定向
假设不在nginx中对auth.com
做重定向, 我们的访问流程应该是这样的:
先看一下, 正常情况下的授权流程:
1
2
3
4
5
6
7
8
9
10
11
|
// 第一步: 访问a.com/vip
const url = encodeURIComponent('auth.com')
window.open("https://open.weixin.qq.com/connect/oauth2/authorize?appid=${process.env.APP_ID}&redirect_uri=${url}&response_type=code&scope=${auth_type}&state=STATE#wechat_redirect")
// 第二步: open.weixin.qq.com
// 会自动跳转到redurec_uri对应的页面 auth.com?code=123456
// 第三步: auth.com?code=123456
// 调用项目接口, 拿code换取用户信息
|
这是一个最简单的授权案例, 但是思考这么一个问题:
微信公众平台的合法授权域名只能绑定2个, 如果公司有三个业务域名a.com, b.com, c.com
, 如果他们在授权后都停留到auth.com
下, 那auth.com
的虚拟主机应该绑定到哪个业务下呢
所以在实际业务中, 最好是把认证业务与普通业务分开处理, 所以最好是只把auth.com当做一个中间平台, 只用来获取微信授权返回的code, 不要让用户在这个域名下处理实际业务. 让auth.com
获取到微信授权返回的code后, 自动跳转到原先的业务域名下即可
要实现这个功能, 我们在第一步中, 给redirect_uri
添加了一个参数origin
, 第三步中可以通过这个参数跳转到最初的项目
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 第一步: 访问a.com/vip
const url = encodeURIComponent('auth.com?origin=a.com/vip')
window.open("https://open.weixin.qq.com/connect/oauth2/authorize?appid=${process.env.APP_ID}&redirect_uri=${url}&response_type=code&scope=${auth_type}&state=STATE#wechat_redirect")
// 第二步: open.weixin.qq.com
// 会自动跳转到redurec_uri对应的页面 auth.com?origin=a.com/vip&code=123456
// 第三步: auth.com?origin=a.com/vip&code=123456
window.open('a.com/vip&code=123456')
// 第四步 a.com/vip&code=123456
// 调用项目接口, 拿code换取用户信息
|
现在出现了一个新的问题: 在这个过程中,浏览器自动跳转了3次, 第三步在跳转的过程中, 依然要在浏览器中加载auth.com
的资源,才能跳转, 能不能把这个步骤放到nginx
当中,在nginx中直接重定向呢?
在nginx
的auth.com
虚拟主机下, 添加如下代码:
1
2
3
4
5
|
location / {
rewrite (.*) $arg_origin permanent;
index index.html;
}
|
再次访问a.com/vip
页面 ,它已经成功的减少了一步自动跳转.
现在又出现了新的问题, 假设我的当前页面地址带有query参数呢?
1
2
3
4
5
6
7
|
// 第一步: 访问a.com/vip?age=20&name=zhangsan
const url = encodeURIComponent('auth.com?origin=a.com/vip?age=20&name=zhangsan')
window.open("https://open.weixin.qq.com/connect/oauth2/authorize?appid=${process.env.APP_ID}&redirect_uri=${url}&response_type=code&scope=${auth_type}&state=STATE#wechat_redirect")
// 第二步: open.weixin.qq.com
// 会自动跳转到redurec_uri对应的页面 auth.com?origin=a.com/vip?age=20&name=zhangsan
|
第二步中就出问题了, 做过微信授权的都知道nignx在解析auth.com?origin=a.com/vip?age=20&name=zhangsan
时, 地址中连续出现了两个?
, 此时的地址会被解析为:
1
2
3
4
|
{
origin:'a.com/vip?age=20',
name:'zhangsan'
}
|
这就导致nginx
会把页面重定向到a.com/vip?age=20
页面,