小程序获取登录code和用户加密信息方法
wx.login({
success(res) {
console.log("postLogin login success", res);
if (!res.code) {
reject();
}
wx.getUserInfo({
withCredentials: true,
success(userRes) {
app.api.user.postLogin({
'code': res.code,
"signature":userRes.signature,
"rawData":userRes.rawData,
'encryptedData': userRes.encryptedData,
'iv': userRes.iv
}).onSuccess(function (res) {
if (res) {
resolve(res);
} else {
reject();
util.showErrorMessage("登录失败");
}
}).onFail(function (res) {
reject();
util.showErrorMessage(res.msg);
}).start();
}
})
}
});
小程序传参对象类WxLoginVO,代码注释已经说明相关参数,这里就不做解释
package com.frank.lmsg.vo.req;
import java.io.Serializable;
/**
*
* Description: 用户信息 微信登录验证VO
* Auth: Frank
* Date: 2019-08-09
* Time: 下午 2:22
*/
public class WxLoginVO implements Serializable {
/**
* 对应小程序获取用户信息的encryptedData字段
*/
private String encryptedData;
/**
* 对应小程序获取用户信息的iv字段
*/
private String iv;
/**
* 对应小程序获取用户信息的rawData字段
*/
private String rawData;
/**
* 对应小程序获取用户信息的signature字段
*/
private String signature;
/**
* 对应小程序登录的时候反的code字段
*/
private String code;
public String getEncryptedData() {
return encryptedData;
}
public void setEncryptedData(String encryptedData) {
this.encryptedData = encryptedData;
}
public String getIv() {
return iv;
}
public void setIv(String iv) {
this.iv = iv;
}
public String getRawData() {
return rawData;
}
public void setRawData(String rawData) {
this.rawData = rawData;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String toString() {
return "WxLoginVO{" +
"encryptedData='" + encryptedData + '\'' +
", iv='" + iv + '\'' +
", rawData='" + rawData + '\'' +
", signature='" + signature + '\'' +
", code='" + code + '\'' +
'}';
}
}
微信相关工具类WxUtils,代码注释已经说明相关方法,这里就不做解释
package com.frank.lmsg.base.utils;
import com.alibaba.fastjson.JSONObject;
import com.frank.lmsg.constant.WxConsts;
import com.frank.lmsg.vo.resp.UserInfoVo;
import com.frank.lmsg.vo.resp.WxUserInfoVO;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.logging.log4j.LogManager;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Base64;
/**
* 微信用户信息解密工具
*
* @author Giam
* @version 1.0
* @date 2019/6/19
*/
public class WxUtils {
/**
* 微信获取用户信息 encryptedData解密
* <p>
* 解密算法如下:
* 1.对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
* 2. 对称解密的目标密文为 Base64_Decode(encryptedData)。
* 3. 对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
* 4. 对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。
* </p>
*
* @param encryptedData 加密的数据
* @param sessionKey sessionKey
* @param iv iv
* @return
*/
public static WxUserInfoVO encryptedDataUserInfo(String encryptedData, String sessionKey, String iv){
// 被加密的数据
Base64.Decoder decoder = Base64.getDecoder();
byte[] dataByte = decoder.decode(encryptedData);
// 加密秘钥
byte[] keyByte = decoder.decode(sessionKey);
// 偏移量
byte[] ivByte = decoder.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, StandardCharsets.UTF_8);
return JSONObject.parseObject(result, WxUserInfoVO.class);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获得微信signature
* signature = sha1( rawData + session_key )
* @param rawData rawData
* @param sessionKey sessionKey
* @return
*/
public static String getSignature(String rawData, String sessionKey) {
StringBuffer signatureStr = new StringBuffer();
signatureStr.append(rawData);
signatureStr.append(sessionKey);
return DigestUtils.sha1Hex(signatureStr.toString().getBytes());
}
/**
* 获取登录信息URL并拼接相关参数
* @param api
* @param arg
* @return
*/
public static String getApi(String api, Object... arg) {
String url = String.format(api, WxConsts.APP_ID, WxConsts.APP_SECRET);
url = MessageFormat.format(url, arg);
return url;
}
}
登录微信请求工具类HttpUtils,代码注释已经说明相关方法,这里就不做解释
package com.frank.lmsg.base.utils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
public class HttpUtils {
public static String doGet(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = "";
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
// 创建http GET请求
HttpGet httpGet = new HttpGet(uri);
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doGet(String url) {
return doGet(url, null);
}
}
详细代码可以查看:
https://github.com/fuxingkai/LMsg
https://github.com/fuxingkai/LMsg-B
参考地址:
https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserInfo.html
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
网友评论