項(xiàng)目背景
使用uniapp開發(fā)微信小程序,避免不了微信登錄。但自動(dòng)微信2022年升級(jí)了api版本后,不再允許返回昵稱和頭像信息,所以才出現(xiàn)無感登錄或授權(quán)手機(jī)號(hào)登錄。實(shí)現(xiàn)方式大同小異。
java后端所需maven
1、小程序無感登錄
前端實(shí)現(xiàn)代碼:
onLoad() {
if (!uni.getStorageSync("token")) {
this.showLogin = true;
uni.login({
provider: 'weixin',
success: (loginRes) => {
this.code = loginRes.code;
//此處將code傳入后端進(jìn)行解析到openid,最終得到登錄后的token緩存到本地即可
}
})
}
}
由于使用uni.login并不需要用戶授權(quán),所以能做到無感登錄。
后端實(shí)現(xiàn):
/**
微信登錄工具類
**/
public class WechatGetUserInfoUtil {
public static final String APPID = "wxd5fc6c544e752529";
public static final String SECRET = "c2bf267226c0157c859da6934ee3c298";
/**
根據(jù)微信小程序登錄獲得的code獲取用戶信息
*/
public static Map<String, String> getWxLoginInfo(String code) {
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + APPID + "&secret=" + SECRET + "&js_code=" + code + "&grant_type=authorization_code";
String responseBody = HttpUtil.get(apiUrl);
Map jsonObject = new Gson().fromJson(responseBody, Map.class);
Map<String, String> map = new HashMap<>();
map.put("openid", jsonObject.get("openid").toString());
map.put("session_key", jsonObject.get("session_key").toString());
return map;
}
}
通過以上方法可以對(duì)應(yīng)的openid,然后通過openid可以得到用戶信息,如果不存在用戶信息,則創(chuàng)建一個(gè)用戶即可。默認(rèn)頭像和隨機(jī)數(shù)昵稱值即可。
2、授權(quán)手機(jī)號(hào)登錄
授權(quán)手機(jī)號(hào)登錄相對(duì)于無感登錄是相對(duì)復(fù)雜一點(diǎn),但也還好。
前端:(ps:此處前端框架使用了uView,只是樣式上有所變化)
<template>
<view>
<!-- 登錄授權(quán)彈出層 -->
<u-popup :show="showLogin" mode="center" round="10rpx" @close="showLogin=false">
<view class="login_view">
<view class="content_view">
<image src="../../static/logo.png"></image>
<view>親,授權(quán)手機(jī)號(hào)后才能正常使用相關(guān)功能</view>
</view>
<view class="btn_view">
<u-button type="primary" open-type="getPhoneNumber" @getphonenumber="login" color="#43ad47"
shape="circle" text="授權(quán)登錄"></u-button>
</view>
</view>
</u-popup>
</view>
</template>
<script>
export default {
data() {
return {
showLogin: false,
code:''
}
},
onLoad() {
if (!uni.getStorageSync("token")) {
this.showLogin = true;
uni.login({
provider: 'weixin',
success: (loginRes) => {
this.code = loginRes.code;
}
})
}
},
methods: {
login(e) { //授權(quán)登錄
let obj = {
iv: e.detail.iv,
encryptedData: e.detail.encryptedData,
code: this.code
}
if (e.detail.iv) {
wxlogin(obj).then(res => {
this.showLogin = false;
uni.setStorageSync('token', res.data.access_token);
uni.showToast({
title: "登錄成功",
icon: "none",
duration: 2000
})
})
} else {
uni.$u.toast('授權(quán)失敗,請(qǐng)聯(lián)系管理員');
}
},
}
</script>
<style lang="scss">
.login_view {
width: 630rpx;
height: 400rpx;
.title_view {
font-size: 36rpx;
color: #333;
text-align: center;
padding: 20rpx;
}
.content_view {
margin: 50rpx;
margin-bottom: 20rpx;
font-size: 28rpx;
text-align: center;
image {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
}
view {
margin-top: 20rpx;
}
}
.btn_view {
margin: 30rpx;
}
}
</style>
注意,獲取手機(jī)號(hào)需要用戶點(diǎn)擊按鈕觸發(fā)后方可獲取,不然是無法獲取到手機(jī)號(hào)信息的。
獲取code一定要在授權(quán)之前獲取,否則后端無法解密出對(duì)應(yīng)的手機(jī)號(hào)信息。
后端實(shí)現(xiàn):
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import com.google.gson.Gson;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class WechatGetUserInfoUtil {
public static final String APPID = "wxd5fc6c544e752529";
public static final String SECRET = "c2bf267226c0157c859da6934ee3c298";
public static Map<String, String> getWxLoginInfo(String code) {
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + APPID + "&secret=" + SECRET + "&js_code=" + code + "&grant_type=authorization_code";
String responseBody = HttpUtil.get(apiUrl);
Map jsonObject = new Gson().fromJson(responseBody, Map.class);
Map<String, String> map = new HashMap<>();
map.put("openid", jsonObject.get("openid").toString());
map.put("session_key", jsonObject.get("session_key").toString());
return map;
}
/**
* 解密用戶手機(jī)號(hào)
*
* @param encryptedData 包括敏感數(shù)據(jù)在內(nèi)的完整用戶信息的加密數(shù)據(jù)
* @param iv 加密算法的初始向量
*/
public static String getMobile(String encryptedData, String sesskey, String iv) {
String result = decryptData(encryptedData, sesskey, iv);
if (result == null) {
return null;
}
Map<String, String> map = new JSONObject(result).toBean(Map.class);
return map.get("phoneNumber");
}
public static String decryptData(String encryptedData, String sessionKey, String iv) {
// 被加密的數(shù)據(jù)
byte[] dataByte = Base64Utils.decode(encryptedData.getBytes());
// 加密秘鑰
byte[] keyByte = Base64Utils.decode(sessionKey.getBytes());
// 偏移量
byte[] ivByte = Base64Utils.decode(iv.getBytes());
try {
// 如果密鑰不足16位,那么就補(bǔ)足. 這個(gè)if 中的內(nèi)容很重要
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 result;
}
} catch (NoSuchAlgorithmException e) {
log.error(e.getMessage(), e);
} catch (NoSuchPaddingException e) {
log.error(e.getMessage(), e);
} catch (InvalidParameterSpecException e) {
log.error(e.getMessage(), e);
} catch (IllegalBlockSizeException e) {
log.error(e.getMessage(), e);
} catch (BadPaddingException e) {
log.error(e.getMessage(), e);
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(), e);
} catch (InvalidKeyException e) {
log.error(e.getMessage(), e);
} catch (InvalidAlgorithmParameterException e) {
log.error(e.getMessage(), e);
} catch (NoSuchProviderException e) {
log.error(e.getMessage(), e);
}
return null;
}
}
實(shí)現(xiàn)時(shí)需要先調(diào)用:getWxLoginInfo得到openid和session_key信息,然后調(diào)用獲取手機(jī)號(hào)getMobile得到手機(jī)號(hào),最后通過openid取獲取用戶信息,如果不存在,則創(chuàng)建一個(gè)用戶,并設(shè)置openid和手機(jī)號(hào)信息,最后返回token即可。
3、修改用戶昵稱頭像信息
前端:
<button class="authorization" type="default" open-type="chooseAvatar" @chooseavatar="chooseavatar" >上傳微信頭像</button>
<input id="nickname-input" v-model="nickname" v- class="authorization white" type="nickname" placeholder="請(qǐng)輸入用戶昵稱" >
chooseavatar(e) {
this.avater = this.avater;//如果需要上傳頭像,則先上傳再賦值
},
此處不是很完善,后面完善
4、獲取定位信息
前端:
uni.getLocation({
type: 'gcj02',
success: function(res) {
///處理業(yè)務(wù)
res.latitude
res.longitude
},
fail: function(err) {
console.log("授權(quán)失敗");
}
});
需要打開manifest.json進(jìn)行配置請(qǐng)求定位權(quán)限
注意:微信開發(fā)者工具中,不支持定位,也不會(huì)彈出授權(quán)申請(qǐng),只有在手機(jī)上才可以,所以微信開發(fā)者工具上時(shí),可以采用設(shè)置默認(rèn)值進(jìn)行測試。文章來源:http://www.zghlxwxcb.cn/news/detail-590906.html
如果需要持續(xù)定位,則需要單獨(dú)申請(qǐng)后臺(tái)定位授權(quán),具體前往uniapp查看。文章來源地址http://www.zghlxwxcb.cn/news/detail-590906.html
到了這里,關(guān)于基于uniapp+java實(shí)現(xiàn)微信小程序無感登錄,授權(quán)手機(jī)號(hào)登錄,獲取昵稱頭像,獲取定位信息的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!