1、逻辑如下
1、通过uni.login获取用户的code
2、通过code获取secretKey,用于解码
3、调用uni.getUserProfile获取encryptedData ,和iv,将上面的secretKey,一起传到后端用于解码,获取用户的信息。
参考文章 文章链接
2、uni前端方法的设计如下
(1)点击登录调用的方法
hasLogin() {
let signature = null;
let encryptedData = null
let iv = null
let that_ = this;
// encryptedData字段
uni.getUserProfile({
desc: "授权登录",
lang: "zh_CN",
success: function(resTwo) {
iv = resTwo.iv;
encryptedData = resTwo.encryptedData;
uni.login({
provider: 'weixin',
success: function(loginRes) {
if (loginRes.errMsg == "login:ok") {
const code = loginRes.code;
api.getSessionKey(loginRes.code).then(res => {
signature = res.data;
let data = {
signature,
iv,
encryptedData
}
api.getUserInfo(data).then(rrr => {
console.log(rrr)
that_.hasLoginww = true
that_.userInfo.imageUrl = rrr.data
.avatarUrl;
that_.userInfo.nickname = rrr.data
.nickName;
that_.userInfo.username = rrr.data
.watermark.appid;
})
})
}
}
});
}
})
}
(2)、前端封装的两个接口
接口一、通过code获取sessionkey
getSessionKey(data) {
return request({
url: `/test/userInfo4/${data}`,
method: 'GET',
})
},
接口二、通过sessionKey和encryptedData 和iv获取用户详细信息,包括用户的唯一openId
getUserInfo(data) {
return request({
url: `/test/userInfo2`,
method: 'POST',
data
})
},
3、java后端接口
(1)、调用接口获取用户的sessionKey
@GetMapping("/userInfo4/{code}")
public Result getUserInfo4( @PathVariable String code){
System.out.println(code+"值");
String onlinePeople = SessionKey.getOnlinePeople2(code);
return Result.ok(onlinePeople);
}
采用get调用微信的接口,获取sessionKey
public static final String ONLINE_PEOPLE_URL = "https://api.weixin.qq.com/sns/jscode2session";
public static final String APP_ID = "在微信小程序后台获取";
public static final String SECRET = "在微信小程序后台获取";
public static final String GRANT_TYPE = "authorization_code";
public static String getOnlinePeople(String code) {
JsonObject object = null;
try {
String baseUrl = ONLINE_PEOPLE_URL + "?appid=" + APP_ID + "&secret=" + SECRET + "&js_code=" + code + "&grant_type=" + GRANT_TYPE;
URL url = new URL(baseUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 打开连接
connection.connect();// 连接会话
// 获取输入流
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {// 循环读取流
sb.append(line);
}
br.close();// 关闭流
connection.disconnect();// 断开连接
System.out.println("拿到GET结果" + sb.toString());
JsonParser parse =new JsonParser();
object= (JsonObject) parse.parse(sb.toString());
JsonElement data = object.get("session_key");
// JsonElement data2 = object.get("status");
String asString = data.getAsString();
return asString;
} catch (Exception e) {
e.printStackTrace();
System.out.println("失败!");
}
return null;
}
(2)通过用户的sessionKey和encryptedData ,和iv ,在后台将encryptedData进行解码并返回用户信息。
这个可以自己后台处理,返回相对应的信息,可以通过判断appid是否存在,如果存在就返回用户信息及token和refreshToken等信息。如果不存在,则可以跳转注册等情况。
后台controller层接口,接收上面三个参数
@PostMapping("/userInfo2")
public Result getUserInfo2( @RequestBody UserREQ userREQ){
JSONObject userInfo = TMyBase.getUserInfo(userREQ.getEncryptedData(), userREQ.getSignature(), userREQ.getIv());
return Result.ok(userInfo);
}
对用户信息进行解码
public class TMyBase {
public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv){
// 被加密的数据
byte[] dataByte = Base64.decode(encryptedData);
// 加密秘钥
byte[] keyByte = Base64.decode(sessionKey);
// 偏移量
byte[] ivByte = Base64.decode(iv);
try {
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
// 初始化
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
parameters.init(new IvParameterSpec(ivByte));
cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
byte[] resultByte = cipher.doFinal(dataByte);
if (null != resultByte && resultByte.length > 0) {
String result = new String(resultByte, "UTF-8");
return JSONObject.parseObject(result);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}