大家好,最近工作有个项目是做小程序,需要用到微信登录,于是稍加研究了一下下面是给大家整理的内容
首先对接微信登录,微信会提供一个api
在调用这个api的时候需要一个HttpClient工具
private static final CloseableHttpClient httpclient = HttpClients.createDefault();
/**
* 发送HttpGet请求
* @param url 请求地址 *
* @return 返回字符串
*/
public static String sendGet(String url, Map<String, String> headerList) throws Exception{
String result = null;
CloseableHttpResponse response = null;
try {
HttpGet httpGet = new HttpGet(url);
if(headerList != null){
Set<String> keySet = headerList.keySet();
for (String key :keySet) {
httpGet.setHeader(key, headerList.get(key));
}
}
response = httpclient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity);
}
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
此工具类需要两个依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
<scope>compile</scope>
</dependency>
在这个api中,前端调用微信的wx.login接口会得到一个code码,得到这个code码,在发送给后台,后台就会得到session_key以及openId
注: session_key解密微信数据包的,而openId是微信返回的唯一标识,可以直接存储到数据库中
得到session_key和openId之后前端再次调用wx.getUserInfo/wx.getUserProfile 接口会得到微信加密的数据包,以及加密算法的初始向量等
public void getAuth(Map<String,Object> params){
String url = ""; //此处是你的api params中会携带参数入jsCode,iv,rawData,userInfo等参数
try {
String sendGet = sendGet(url, null);
JSONObject jsonObject = JSONObject.parseObject(sendGet);
Object openId = jsonObject.get("openId");
Object session_key = jsonObject.get("session_key");
} catch (Exception e) {
e.printStackTrace();
}
}
需要注意: 前端在调用wx.login和wx.getUserInfo的时候只调用后端的一个接口就可以了,前端获取到jsCode以及加密的数据包和IV等数据时,直接调用后端接口,由后端操作!
得到了session_key之后,我们就可以解密数据,我们需要一个解密的数据util,注: 使用这个util的时候注意导包的位置
package **.**.utils;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
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;
/***
* @author gxh
* 获取微信隐私数据并解密
*/
public class AesUtil {
static {
//BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/
Security.addProvider(new BouncyCastleProvider());
}
/**
* AES解密
*
* @param data //密文,被加密的数据
* @param key //秘钥 sessionKey
* @param iv //偏移量
* @param encodingFormat //解密后的结果需要进行的编码
* @return
* @throws Exception
*/
public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {
//被加密的数据
byte[] dataByte = Base64.decodeBase64(data);
//加密秘钥
byte[] keyByte = Base64.decodeBase64(key);
//偏移量
byte[] ivByte = Base64.decodeBase64(iv);
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
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, encodingFormat);
return result;
}
return null;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
此工具类需要的pom坐标
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version>
</dependency>
得到这个界面算法之后我们就可以解密数据了,login接口就可以是这样的了
public void getAuth(Map<String,String> params){
String url = "";
try {
//获取api中的session_key
String sendGet = sendGet(url, null);
JSONObject jsonObject = JSONObject.parseObject(sendGet);
Object openId = jsonObject.get("openId");
String session_key = (String) jsonObject.get("session_key");
//解密微信数据
String decrypt = decrypt(params.get("data"), session_key, params.get("iv"), "UTF-8");
JSONObject resultJson = JSONObject.parseObject(decrypt);
//获取数据
String nickName = resultJson.getString( "nickName" );
String avatarUrl = resultJson.getString( "avatarUrl" );
String gender = resultJson.getString( "gender" );
String city = resultJson.getString( "city" );
String country = resultJson.getString( "country" );
String province = resultJson.getString( "province" );
} catch (Exception e) {
e.printStackTrace();
}
}
说一下思路:
1: 获取到了微信返回的数据之后就可以存储到数据库中,openId是一定要存的,是微信用户的唯一标识符,
2: 获取到微信的信息之后就要给微信用户给我们系统的认证了
好了今天就到这里