因为要通过用户信息是加密的内容,所以需要对信息进行解密,原本用JFinal的封装好的方法进行解密,但是一直报错,所以在网上整合了一下别人的代码,并完成了解密,现在把代码贴出来,以供大家和自己以后使用。
首先需要的架包:
<!-- 解密需要用的jar --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.57</version> </dependency>
- 需要注意的是,AES解密的时候需要用到javax.crypto.*包的类,在jdk的 jce.jar中提供,是jdk自带的库。如果是MAVEN项目,则需要在pom.xml文件中配置指定编译路径jce.jar
在bootclasspath中添加jce.jar的地址:<bootclasspath>${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/jre/lib/jce.jar</bootclasspath> ,注意rt.jar 和 jce.jar 间以:号连接
如:
<build> <finalName>com.yfs.app</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <source>1.7</source> <target>1.7</target> <compilerArguments> <verbose /> <bootclasspath>${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/jre/lib/jce.jar</bootclasspath> </compilerArguments> <encoding>utf-8</encoding> </configuration> </plugin> </plugins> </build>
这些都配置好以后,就可以写一个解密的工具类了
package com.jmt.wx.util; import com.alibaba.fastjson.JSONObject; import com.jfinal.weixin.sdk.api.ApiResult; import com.jfinal.weixin.sdk.encrypt.WxaBizDataCrypt; 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; import java.util.Arrays; /** * Created by yfs on 2017/2/6. * <p> * AES-128-CBC 加密方式 * 注: * AES-128-CBC可以自己定义“密钥”和“偏移量“。 * AES-128是jdk自动生成的“密钥”。 */ public class JieMiUtil { static { //BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/ Security.addProvider(new BouncyCastleProvider()); } /** * AES解密 * * @param data //密文,被加密的数据 * @param key //秘钥 * @param iv //偏移量 * @param encodingFormat //解密后的结果需要进行的编码 * @return * @throws Exception */ public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception { // initialize(); //被加密的数据 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; } }
redisTemplate工具类:
package com.jmt.wx.util; import java.util.Date; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; public class CacheUtil{ @Autowired private StringRedisTemplate redisTemplate;//redis操作模板 public void put(String key, String value) { if (key==null || "".equals(key)) { return; } redisTemplate.opsForHash().put(key, key, value); } public String get(String key) { Object obj = redisTemplate.opsForValue().get(key); if(obj == null){ return null; }else{ return String.valueOf(obj); } } public void expire(String key,String value,long time,TimeUnit timeUnit ){ redisTemplate.opsForValue().set(key, value, time, timeUnit); } /* * 销毁 */ public void delete(String key){ redisTemplate.delete(key); } /** * 根据key 获取指定单位的过期时间 */ public long getTimeByKey(String Key){ long time2=redisTemplate.boundHashOps(Key).getExpire(); return time2; } public long getOutTime(String key){ long time=redisTemplate.getExpire(key); return time; } /** * 检查key是否存在 * 如果不存在,证明没有session */ public boolean CheckSession(String key){ return redisTemplate.hasKey(key); } }
服务端代码:
/** * 服务端解密用户信息接口 * 获取unionId * return unionid 返回获取的unionID */ public void encryptedData() { JSONObject returnInfo = new JSONObject(); String encryptedData = getPara("encryptedData"); String iv = getPara("iv"); String code = getPara("code"); //登录凭证不能为空 if (code == null || code.length() == 0) { returnInfo.put("status", 0); returnInfo.put("msg", "code 不能为空"); renderJson(returnInfo); return; } //小程序唯一标识 (在微信小程序管理后台获取) String wxspAppid = "*********************"; //小程序的 app secret (在微信小程序管理后台获取) String wxspSecret = "********************"; //授权(必填) String grant_type = "authorization_code"; /////////////////////////////////////////////////// // 调用微信api,用code 换取openId和session_key // 返回示例{"session_key":"ycGF02Ha\/dnZ6Tc829xw7Q==","expires_in":7200,"openid":"oZ2Xq0Byh0wqtUi-j-RgJ1atLPdo"} String url = "https://api.weixin.qq.com/sns" + "/jscode2session?appid=" + wxspAppid + "&" + "secret=" + wxspSecret + "&js_code=" + code + "&" +grant_type; CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpget = new HttpGet(url); String sessionKey=null; try { CloseableHttpResponse response = httpClient.execute(httpget); int statusCode = response.getStatusLine().getStatusCode(); JSONObject resultJson = null; if (statusCode == HttpStatus.SC_OK) { String reslut = EntityUtils.toString(response.getEntity()); resultJson = JSONObject.parseObject(reslut); sessionKey = resultJson.getString("session_key"); String openid = resultJson.getString("openid"); //添加session到redis缓存中 //把sessionKey和APPId设置成session,这里用的是redisTemplate模板 String Third_session=null; if (sessionKey != null && openid != null) { Third_session = SessionUtil.generateSessionId();//随机生成长度为16B cacheUtil.expire(Third_session, sessionKey+openid, Integer.parseInt(Gloal.getProperty("CACHE_TIME")), TimeUnit.SECONDS); System.out.println(new Date() + "设置sessionKey:" + Third_session); System.out.println(new Date() + "设置sessionValue:" + sessionKey + openid); } //////////////// 2、对encryptedData加密数据进行AES解密 //////////////// String result = JieMiUtil.decrypt(encryptedData, sessionKey, iv, "UTF-8"); if (null != result && result.length() > 0) { returnInfo.put("errCode",ErrCode.SUCCESS); returnInfo.put("msg", "解密成功"); JSONObject userInfoJSON = JSONObject.parseObject(result); Map userInfo = new HashMap(); userInfo.put("openId", userInfoJSON.get("openId")); userInfo.put("nickName", userInfoJSON.get("nickName")); userInfo.put("gender", userInfoJSON.get("gender")); userInfo.put("city", userInfoJSON.get("city")); userInfo.put("province", userInfoJSON.get("province")); userInfo.put("country", userInfoJSON.get("country")); userInfo.put("avatarUrl", userInfoJSON.get("avatarUrl")); userInfo.put("unionId", userInfoJSON.get("unionId")); userInfo.put("third_session",Third_session); returnInfo.put("userInfo", userInfo); renderJson(returnInfo); return; } } ///////////////////////////////////////////// returnInfo.put("errCode", ErrCode.RESULT_NULL); returnInfo.put("msg", "fail"); renderJson(returnInfo); return; } catch (Exception e) { e.printStackTrace(); returnInfo.put("errCode", ErrCode.RESULT_NULL); returnInfo.put("msg", "fail"); renderJson(returnInfo); return; }finally { if (httpget != null) { httpget.releaseConnection(); } } }
到此为止,用户信息解密成功。
总结
好了,总算完成数据解密了,接下来对接新的或已有的用户系统都妥妥的。
有一点需要注意的是,要对接已有的用户系统可能需要用到unionId,如果通过以上方法获取不到unionId,那么你就要去检查一下你的微信开放平台(微信开放平台)是否有绑定微信小程序咯~
本文借鉴了 微信小程序联盟 的文章,有想看的可以去看下哦