实现微信公众号授权登录,很简单,但是注意的地方要细心,小伙伴们跟着我的思路一起实现吧!
文章目录
一、帐号申请
如果只是为了开发测试,建议使用测试账号,真正需要的时候再进一步需求即可。
为了演示方便,这里使用微信测试账号
1. 正式账号
- 1.账号申请
官网链接:https://mp.weixin.qq.com/
授权登录测试需要访问公网,因此,需要自己购买域名服务器、以及通过DNS解析将域名备案、域名和服务器绑定。
具体购买途径:请小伙伴们自己百度吧
2. 测试帐号
微信公众平台接口测试帐号申请
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
打开微信公众平台登录,用微信扫码登录
把appID和appsecret复制到txt文本中,等会用
appID:wxd1f5xxx72428a
appsecret:a179826ae2aaff32xxx1551f315c43bc
说明:请使用自己的测试账号
二、微信文档
2.1. 文档主页
打开微信官网文档选择-公众号
https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
2.2. 授权流程
微信网页开发 /网页授权
实现流程一共5步
- 1 第一步:用户同意授权,获取code
- 2 第二步:通过code换取网页授权access_token
- 3 第三步:刷新access_token(如果需要)
- 4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
- 5 附:检验授权凭证(access_token)是否有效
这里会有二种场景,
第一种:非前后端分离项目,请参考这篇
第二种:如果是前后端分离项目,第一步是前端项目页面要做的,其余的2、3、4、5步都在后端项目中执行。
说明:如果是前后端分离项目依次执行1、2、3、4、5步会出现跨域问题
回到测试账号页面,找到网页帐号/网页授权获取用户基本信息/无上限/修改,点击修改,补充域名信息,这里演示采用ip和端口形式,正式环境请使用域名,不要带有端口。
- 1 第一步:用户同意授权,获取code
有二种方式,由于我们需要用户的详细信息,因此,这里采用scope为snsapi_userinfo这种
2.3. 授权回调
这里配置的是回调页面的域名,测试账号可以使用ip和端口,正式账号官网只允许使用域名。
三、前端部分
这里在用户点击菜单式,跳转主页面,渲染页面时自动引导用户进行登录授权,因此来获取用户信息,用来区分登录用户的身份。
3.1. 登录校验
为了避免多次重复获取用户信息,当前用户登录后,将用户信息保存到本地缓存中,如果从班底缓存中获取不到用户信息,前端就发起请求微信接口获取code,携带code请求后端,由后端完成授权登录剩下的流程,最终将用户信息返回前端,保存到本地缓存中。
mounted() {
// debugger
const user = storage.get("userInfo") || {}
if (Tool.isEmpty(user)) {
// 如果缓存localStorage中没有userInfo,则需用code去后台获取
this.getCode();
}
},
3.2. code获取
methods: {
getCode() {
// 非静默授权,第一次有弹框
this.code = '';
var callback_url = Wxconst.CALLBACK_URL; // 获取页面url
var appid = Wxconst.APPID;
this.code = this.getUrlCode().code; // 截取code
if (this.code == null || this.code === '') {
// 如果没有code,则去请求
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${encodeURIComponent(
callback_url
)}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`;
} else {
// 当code不等于空时,调用后端接口获取用户信息
this.getUserInfo();
// 你自己的业务逻辑
}
},
// 从url中获取code返回
getUrlCode() {
// 截取url中的code方法
var url = location.search;
this.winUrl = url;
var theRequest = new Object();
if (url.indexOf('?') != -1) {
var str = url.substr(1);
var strs = str.split('&');
for (var i = 0; i < strs.length; i++) {
theRequest[strs[i].split('=')[0]] = strs[i].split('=')[1];
}
}
return theRequest;
}
}
3.3. 请求后端
<script>
import {login} from '@/https/http.js';
methods: {
getUserInfo() {
login(this.code).then((res) => {
// console.log('openid' + res.content.openid);
// console.log('nickname' + res.content.nickname);
// console.log('headimgurl' + res.content.headimgurl);
storage.set('userInfo', res.content)
});
},
}
</script>
api接口
export function login(params) {
return instance.post('/wxh5/login?code='+params)
}
request.js
// 导入axios
import axios from 'axios';
// 使用自定义配置新建一个axios 实例,对axios 做一些基础配置
const instance = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_SERVER,
// baseURL: "http://127.0.0.1:8080/",
timeout: 50000,
headers: {'X-Custom-Header': 'foobar'}
});
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
//请求之前执行该函数, 一般在该处设置token
let token = localStorage.getItem("token");
if (token) {
config.headers["token"] = token
}
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
//响应拦截器
instance.interceptors.response.use(response => {
//1.非200响应
//2.token过期
//3.异地登陆
//4.非对象加密的解密
console.log('返回结果:', response);
return response;
}, error => {
console.log('返回错误:', error);
const response = error.response;
const status = response.status;
if (status === 401) {
// 判断状态码是401 跳转到首页或登录页
console.log("未登录,跳到首页");
store.commit("setUser", {});
message.error("未登录或登录超时");
router.push('/');
}
return Promise.reject(error);
})
export default instance
四、工具下载
4.1. 工具下载
4.2. 启动项目
npm run dev
or
npm run serve
打开项目
使用微信开发工具扫码登录,选择公众号网页
4.3. 主页访问
把主页路径复制到微信公众号开发工具中,我的主页路径是http://localhost/
输入http://localhost/,点击回车就会好处下以下图:
从上面截图可知需要先关注测试账号,用手机号扫描此测试二维码
4.4. 关注公众号
4.5. 再次请求
咱们继续回到微信公众号开发工具中,我的主页路径是http://localhost/
说明:第一次会出现是否确认获取你的微信信息,点击允许,微信就会回调redirect_uri,这个就是微信回调的地址
然后通过getUrlCode()方法从回调的url中获取code
this.code = this.getUrlCode().code; // 截取code