微信小程序登录流程

微信小程序登录流程

1.通过wx.login获取sessionId(开发者服务器自定义标识)

获取解密数据密钥session_key

https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code

2.通过getUserProfile方法获取用户信息

encryptedData
iv
sessionId

通过sessionId获取session_key

解密数据返回前端

小程序前端

wxml

1
2
3
4
5
6
<view class="container">
<view class="userinfo">
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取用户手机号</button>
</view>
</view>

js

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// index.js
// 获取应用实例
const app = getApp()

Page({
data: {
canIUseGetUserProfile: true
},
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad() {},

onShow(){
this.login();
},

login(){
// 登录
wx.login({
success: res => {
console.log(res)
wx.request({
url: 'https://18ab-183-14-132-243.ngrok-free.app/getSessionId',
data: {
code: res.code
},
success: (res) => {
console.log(res)
this.setData({
sessionId: res.data.res
});
}
})
}
})
},

// 获取头像昵称
getUserProfile(e) {
let sessionId = this.data.sessionId;
wx.getUserProfile({
desc: '获取头像昵称', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res)
wx.request({
url: 'https://18ab-183-14-132-243.ngrok-free.app/authLogin',
method: "post",
data: {
encryptedData: res.encryptedData,
iv: res.iv,
sessionId: sessionId
},
success: (res) => {
console.log(res)
}
})
},
fail: (res) => {
console.log(res)
}
})


},

// 获取手机号
getPhoneNumber(e){
let sessionId = this.data.sessionId;
wx.request({
url: 'https://18ab-183-14-132-243.ngrok-free.app/authLogin',
method: "post",
data: {
encryptedData: e.detail.encryptedData,
iv: e.detail.iv,
sessionId: sessionId
},
success: (res) => {
console.log(res)
}
})
}
})

https://18ab-183-14-132-243.ngrok-free.app

做了内网穿透,映射到本地的127.0.0.1:80端口

SpringBoot后端

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@RestController
public class AuthorController {

@Autowired
private AuthorService authorService;

@GetMapping("/getSessionId")
public Map getSessionId(@RequestParam String code){
return authorService.getSessionId(code);
}


@PostMapping("/authLogin")
public Map authLogin(@RequestBody WXAuth wxAuth) throws Exception {
return authorService.authLogin(wxAuth);
}


}

Service

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.example.demo.service;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.example.demo.req.WXAuth;
import com.example.demo.rsp.UserRsp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AuthorService {

@Autowired
private StringRedisTemplate stringRedisTemplate;


@Autowired
private WxService wxService;



public Map getSessionId(String code) {
String url = "https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code ";
String fullUrl = StrUtil.format(url, code);
String res = HttpUtil.get(fullUrl);
String uuid = UUID.randomUUID().toString();
stringRedisTemplate.opsForValue().set(uuid, res);
HashMap<String, Object> map = new HashMap<>();
map.put("res", uuid);
return map;
}


public Map authLogin(WXAuth wxAuth) throws Exception {
String wxRes = wxService.wxDecrypt(wxAuth.getEncryptedData(), wxAuth.getSessionId(), wxAuth.getIv());
System.out.println(wxRes);
HashMap<String, Object> map = new HashMap<>();
map.put("res", wxRes);
return map;
}
}

实体类

1
2
3
4
5
6
7
8
9
10
package com.example.demo.req;

import lombok.Data;

@Data
public class WXAuth {
private String encryptedData;
private String iv;
private String sessionId;
}

WxService

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
28
29
30
31
32
33
34
package com.example.demo.service;

import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;

@Component
public class WxService {
@Autowired
private StringRedisTemplate redisTemplate;

public String wxDecrypt(String encryptedData, String sessionId, String vi) throws Exception {
// 解密
String json = redisTemplate.opsForValue().get(sessionId);
JSONObject jsonObject = JSON.parseObject(json);
String sessionKey = (String) jsonObject.get("session_key");
byte[] encData = cn.hutool.core.codec.Base64.decode(encryptedData);
byte[] iv = cn.hutool.core.codec.Base64.decode(vi);
byte[] key = Base64.decode(sessionKey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
return new String(cipher.doFinal(encData), "UTF-8");
}
}

微信小程序登录流程
http://cxycsx.vip/2023/06/27/微信小程序/微信小程序登录流程/
作者
程序员陈师兄
发布于
2023年6月27日
许可协议