目录
一、概述
二、登录流程
三、前端代码
四、解读前端代码
1、登录部分
2、检查当前用户是否已登录
3、小程序启动时校验登录
五、阶段性小结
一、概述
最近终于有时间去搞一下准备参加比赛的小程序,小程序一开始设计的是使用邮箱登录,老师建议直接实现微信登录,更加方便,以前没有搞过,这次试一下。
网上实现小程序微信登录的教程不是很多,其中使用java后台的更是少之又少,大部分是基于node.js的,而且网上的教程大部分代码缺头少尾,让人摸不着头脑,所以我打算写一个思路清晰一些的教程。
首先附上微信官方文档给的微信登录流程:
先理解一下几个概念:
code:是小程序通过wx.login()获取的,也是用户注册、登录时,前端向后端发送登录凭证。
openid:是后端使用code作为参数,调用微信接口服务获得的。openid是每个微信用户在一个特定的小程序或公众号中的唯一标识符,可以用来区分不同用户。
session_key:也是后端使用code作为参数,调用微信接口服务获得的。session_key是与当前用户会话相关的密钥,用于进行数据加密和解密。其重要性不及openid,可以选择性使用。
开发者服务器:跑后端代码的服务器。
微信接口服务:微信官方提供的API,开发者可以调用这个API获得 openid 和 session_key 。
二、登录流程
从微信官方文档可以看出,具体流程分为一下几点:
- 在小程序前端,使用 wx.login 获取用户的临时登录凭证 code。
- 将获取到的 code 使用 wx.request 发送给后端服务器。
- 在后端服务器中,使用这个 code 调用微信接口服务得到用户的 session_key 和 openid。可以使用微信提供的登录接口或者第三方库来实现这一步骤。
- 将获取到的 session_key 和 openid 存储到后端数据库中,这样后面可以根据这些信息来识别和关联用户。
- 在后端服务器中,根据 openid 将用户的其他信息存储到数据库中。注意,要确保用户的 openid 是唯一的,可以使用 openid 作为用户的唯一标识。
- 存储完用户信息后,后端可以生成一个用户的 token 并返回给小程序前端。小程序前端可以将这个token存储在storage和本地缓存中。
- 后续的请求可以携带这个 token 进行身份验证和授权。
注意微信新出的规定:
从大概2022年十月份起,不允许小程序在获得用户微信登录授权后,直接通过弹窗方式询问是否可以获得用户的微信头像和昵称。好像是因为好些小程序设置了,如果用户禁止小程序使用头像昵称,小程序就会阻止用户登录,即使用户已经授权了微信登录。官方好像认为这侵犯了用户的权益。(好像是这样,我也不太确定哈)
以前的规定是:如果需要存储用户的其他信息(如昵称、头像等),在小程序前端使用 wx.getUserInfo 获取用户信息。
现在的规定是:当小程序需要让用户完善个人资料时,可以通过微信提供的头像昵称填写能力快速完善。
具体见官方文档 头像昵称填写 | 微信开放文档
后面的文章中,我会讨论一下,在新规定下怎么样获取微信用户头像昵称。
了解完基本流程后,开发者应该获取两个必要的东西,后面用得到:
- AppID(小程序ID)
- AppSecret(小程序密钥)
登录进入 微信公众平台 开发-开发管理-开发者id 即可看到。
这里注意,你微信开发者工具里的 AppID,和你在官网拿到的 AppID,还有保存在后端的 AppID要保持一致,不然后面会出现离谱的错误。还有一点,就是 AppSecret 一定要和 AppID 是同一个小程序的,一定要注意!!
注意,修改appid直接在小程序目录下的project.config.json中修改即可。
经测试,如果直接在微信开发者工具>设置>项目设置>基本信息>appId 修改,project.config.json中的appid不会改变。
而直接在project.config.json中修改,上图中开发者工具的appid会随之修改。
三、前端代码
前端代码的话,我是参考了微信小程序实现用户登录(详)_微信小程序登录_灵魂学者的博客-CSDN博客这篇博客写的,这位大佬的后端是基于node的,但是他的思路是一种循序渐进式的,如果没有耐心看完的话,很可能到一半就崩溃了哈哈哈。
前端代码如下:
Javascript">// app.js
App({
globalData: {
baseAPI: "http://localhost:8081", //后端运行端口号
token: null //微信登陆token
},
onLaunch: function () {
this.checkLogin(res => {
console.log('is_login : ', res.is_login);
if (!res.is_login) {
this.login();
}
})
},
//微信登录逻辑
login: function () {
let _this = this
wx.login({
su***ess: (res) => {
//console.log("code: " + res.code);
wx.request({
url: _this.globalData.baseAPI + "/wxlogin",
header: {
'content-type': 'application/json;charset=UTF-8'
},
method: 'POST',
data: {
code: res.code
},
su***ess: (res) => {
console.log("token : " + res.data.data)
_this.globalData.token = res.data.data
wx.setStorage({
key: 'token',
data: res.data.data
})
},
fail: (error) => {
console.error("QwQ请求失败:", error);
wx.showToast({
title: '请求失败',
icon: 'none',
duration: 2000
});
}
})
}
})
},
//检查是否登录
checkLogin: function (callback) {
let _this = this
var token = _this.globalData.token
if (!token) {
token = wx.getStorageSync('token')
if (token) {
_this.globalData.token = token
} else {
callback({
is_login: false
})
}
}
wx.request({
url: _this.globalData.baseAPI + "/checkwxlogin",
data: {
token: token
},
su***ess: (res) => {
callback({
is_login: res.data.code == 0 ? true : false
})
}
})
},
})
因为微信登录是你打开小程序的时候,就要弹出来的,所以上面的代码要写在 app.js 里面。
四、解读前端代码
1、登录部分
login: function () {
let _this = this
//调用wx.login接口,获取code,即下面的res.code
wx.login({
su***ess: (res) => {
//console.log("code: " + res.code);
wx.request({
url: _this.globalData.baseAPI + "/wxlogin", //调用后端接口
header: {
'content-type': 'application/json;charset=UTF-8'
},
method: 'POST',
data: {
code: res.code //以post方式向后端发送code
},
//从后端接口得到的响应,即res.data
su***ess: (res) => {
console.log("token : " + res.data.data); //后端返回的token保存在res.data.data中
_this.globalData.token = res.data.data // 将token保存至全局 globalData
wx.setStorage({ // 将token保存在storage本地缓存中
key: 'token',
data: res.data.data
})
},
fail: (error) => {
// 输出错误信息到控制台或日志
console.error("QwQ请求失败:", error);
// 弹出提示框显示错误信息
wx.showToast({
title: '请求失败',
icon: 'none',
duration: 2000
});
}
})
}
})
}
注意上面 token 令牌的生成:后端使用 code 调用微信接口服务得到的用户的 session_key 和 openid,将 openid 经过加密变换或者结合时间戳的方式生成的,后面的文章会介绍到。
2、检查当前用户是否已登录
checkLogin: function (callback) {
let _this = this
var token = _this.globalData.token //尝试从全局变量中获取token
if (!token) { //全局变量中没有
token = wx.getStorageSync('token') // 再试试从storage缓存中获取token
if (token) { //storage缓存中有
_this.globalData.token = token
} else { //storage缓存也没有
callback({
is_login: false //回调函数,设置登录状态为 :未登录
})
}
}
// 全局变量中有token,则向后端发送请求检验token是否存在
wx.request({
url: _this.globalData.baseAPI + "/checkwxlogin",
data: {
token: token
},
su***ess: (res) => {
//console.log(res);
callback({
is_login: res.data.code == 0 ? true : false //三元表达式判断,如果res.data.code==0,则赋值is_login为true;其他,则赋值is_login为false
})
}
})
},
})
3、小程序启动时校验登录
onLaunch: function () {
// 小程序启动时检查用户是否登录
this.checkLogin(res => {
console.log('is_login : ', res.is_login);
// 未登录,则调用login()函数
if (!res.is_login) {
this.login();
}
})
}
五、阶段性小结
实现微信登录的前端部分已经实现好了,后续文章会继续介绍如何用Java写后端逻辑、获得用户头像昵称等,尽情期待……