一、登录时序图
引自官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
二、说明
2.1 获取临时登录凭证code
1、调用wx.login获取临时登录凭证code ,并回传到开发者服务器
2、临时登录凭证code只能使用一次
2.2 获取自定义登录态
1、调用auth.code2Session接口,换取用户唯一标识OpenID、用户在微信开放平台账号下的唯一标识UnionID和会话密钥session_key
2、请求参数
属性 | 说明 |
---|---|
appId | 小程序的appId,在开发管理-开发设置获取 |
secret | 小程序 appSecret,在开发管理-开发设置获取 |
js_code | 登录时获取的 code,可通过wx.login获取 |
grant_type | 授权类型,默认值authorization_code |
3、返回值
属性 | 说明 |
---|---|
session_key | 会话密钥 |
unionid | 用户在开放平台的唯一标识符 |
openid | 用户唯一标识 |
2.3 自定义登录态
1、会话密钥session_key是对用户数据进行加密签名的密钥,为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥
2、生成自定义登录态thirdSession,用于第三方服务器和小程序之间做登录状态的校验,可使用UUID生成随机数
3、以thirdSession为key,session_key+openId为value存储起来,可以使用redis存储
2.4 前端处理
1、前端拿到thirdSession后,存储到内存中
2、每次发请求时,带上thirdSession
3、用户进入小程序时,可以调用wx.checkSession检查登录态是否过期
2.5 后端处理
1、后端根据thirdSession从redis中获取session_key、openId
三、开发实现
伪代码实现
/**
* 登录
* https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html
*/
doLogin() {
let that = this;
// 调用wx.login获取code
wx.login({
success (res) {
if (res.code) {
// 向后端发请求,获取自定义登录态
wx.request({
url: 'https://localhost:8080/user/login',
data: {
code: res.code
},
success (res) {
if (res.data.code == 200) {
that.globalData.thirdSession = res.data.thirdSession;
}
}
})
} else {
console.log('登录失败!' + res)
}
}
})
},
/**
* 判断登录状态
* 没有登录过,调用登录方法进行登录
* 已经登录过,判断session_key是否过期
*/
login() {
let that = this;
if (!that.globalData.thirdSession) {
//无thirdSession进行登录
that.doLogin();
} else {
//有thirdSession校验session_key是否过期
wx.checkSession({
success () {
console.log('success');
},
// session_key失效
fail() {
console.log('failed');
that.doLogin();
}
})
}
}
/**
* 登录接口
* LoginVo:private String loginCode;
*/
@ApiOperation(value = "用户登录")
@RequestMapping(value = "/user/login", method = RequestMethod.POST)
public JSONObject login(HttpServletRequest request, @RequestBody LoginVo loginVo);
/**
* 登录逻辑
*/
public JSONObject login(HttpServletRequest request, LoginVo loginVo) {
JSONObject jsonObject = new JSONObject();
try {
String appId = request.getHeader("appId");
String loginCode = loginVo.getLoginCode();
// 组织参数,请求https://api.weixin.qq.com/sns/jscode2session
JSONObject jsCode2Session = get(......);
String openId = jsCode2Session .getString("openid");
String sessionKey = jsCode2Session .getString("session_key");
String unionId = jsCode2Session .getString("unionid");
// 使用openId和数据库交互,有则更新session_key,没有则向数据库增加用户信息
// ......
// 生成thirdSession
String thirdSessionKey = UUID.randomUUID().toString();
// 组织redis中存放的数据
JSONObject thirdSessionObject = new JSONObject();
thirdSessionObject.put("appId", appId);
thirdSessionObject.put("sessionKey", sessionKey);
thirdSessionObject.put("openId", openId);
thirdSessionObject.put("unionId", unionId);
// 数据存储在redis中
redisTemplate.opsForValue().set("THIRD_SESSION_" + thirdSessionKey, JSON.toJSONString(thirdSession), 6, TimeUnit.HOURS);
// 组织返回数据
jsonObject.put("success", true);
jsonObject.put("thirdSession", thirdSessionKey);
jsonObject.put("code", 200);
} catch {
jsonObject.put("success", false);
jsonObject.put("thirdSession", "");
jsonObject.put("code", 500);
}
return jsonObject;
}