java后台微信小程序微信运动之AES解密

想解密微信运动用户的步数,准备步骤:申请一个微信小程序,获取到小程序的APPID,SECRET秘钥,成为微信小程序的开发者以后,开始你的代码搬砖生活。

 

不说废话上代码

//@SysLog("获取用户openid")
@GetMapping("getOpenId")
public Result login(String code)
{
    //微信的接口
    String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+APPID+
            "&secret="+SECRET+"&js_code="+ code +"&grant_type=authorization_code";
    RestTemplate restTemplate = new RestTemplate();
    //进行网络请求,访问url接口
    ResponseEntity  responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
    String sessionKey = null;
    if(responseEntity != null && responseEntity.getStatusCode() == org.springframework.http.HttpStatus.OK) {
        String sessionData = responseEntity.getBody();
        Gson gson = new Gson();
        //解析从微信服务器获得的openid和session_key;
        WeChatSession weChatSession = gson.fromJson(sessionData, WeChatSession.class);
        //获取用户的唯一标识
        String openid = weChatSession.getOpenid();
        //获取会话秘钥
        sessionKey = weChatSession.getSession_key();
        //最后要返回一个自定义的登录态,用来做后续数据传输的验证
        System.out.println("open_id:" + openid + "    session_key:" + sessionKey);
        //此处为我保存数据的方法,可以根据自己的需求去处理
        WX_user wx_user = weChatLoginService.findByOpenId(openid);
        if (wx_user == null) {
            Integer num = weChatLoginService.saveUser(openid);
            if (num == 0) {
                return Result.fail("存储失败");
            }
        }
    }

想要拿到用户的加密步数的数据首先要获得用户的openId,sessionKey,这里就是的代码了,通过前端传来的用户code,后端自行调用微信接口过去用户OpenId,SessionKey

//@SysLog("解密保存微信步数接口")
@GetMapping("/decrypt")
public Result decrypt(String encryptedData, String iv, String sessionKey, String openId) throws Exception{
    System.out.println("date:     "+encryptedData);
    System.out.println("iv:    "+iv);
    System.out.println("openId:   "+openId);
    Map map = new HashMap();
    try {
        AES aes = new AES();
        byte[] resultByte = aes.decrypt(encryptedData, sessionKey, iv);
        if(null != resultByte && resultByte.length > 0){
            String userInfo = new String(resultByte, "UTF8");
            map.put("status", "1");
            map.put("msg", "解密成功");
            map.put("userInfo", userInfo);
            //将微信运动的数据,转换为list
            JSONObject userinfo = JSONObject.fromObject(userInfo);
            String stepInfoList = userinfo.getString("stepInfoList");
            Gson gson = new Gson();
            List list = gson.fromJson(stepInfoList, new TypeToken>() {}.getType());
            System.out.println(list);
        }else{
            map.put("status", "0");
            map.put("msg", "解密失败");
        }
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    Gson gson = new Gson();
    String decodeJSON = gson.toJson(map);
    return Result.success(decodeJSON);
}

此处的代码为解密的代码,AES为封装好的解密的工具类,调用工具类中的decrypt的方法,接下来是已经解密成功的数据,处理数据,转换成list

/**
 * Created by xac on 2018/08/31.
 */
public class AES {

    // 算法名称
    final String KEY_ALGORITHM = "AES";
    // 加解密算法/模式/填充方式
    final String algorithmStr = "AES/CBC/PKCS7Padding";
    //
    private Key key;
    private Cipher cipher;

    public void init(byte[] keyBytes) {

        // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
        int base = 16;
        if (keyBytes.length % base != 0) {
            int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp, (byte) 0);
            System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
            keyBytes = temp;
        }
        // 初始化
        Security.addProvider(new BouncyCastleProvider());
        // 转化成JAVA的密钥格式
        key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
        try {
            // 初始化cipher
            cipher = Cipher.getInstance(algorithmStr);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    public byte[] decrypt(String encryptedDataStr, String keyBytesStr, String ivStr) {
        byte[] encryptedText = null;
        byte[] encryptedData = null;
        byte[] sessionkey = null;
        byte[] iv = null;

        try {
            sessionkey = Base64.decodeBase64(keyBytesStr);
            encryptedData = Base64.decodeBase64(encryptedDataStr);
            iv = Base64.decodeBase64(ivStr);

            init(sessionkey);

            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            encryptedText = cipher.doFinal(encryptedData);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return encryptedText;
    }

这些就是AES工具类解密的代码了,这里解密需要的参数就是前端调去微信传回来的data,iv和用户的sessionKey

 

所以解密并没有想象中那么难,但是有几个坑,解密的时候要注意看微信的开发者文档,文档中已经明确说明加密填充方式

java后台微信小程序微信运动之AES解密_第1张图片

还有一点需要注意的就是用户的sessionKey,开发文档中没有明确声明sessionKey的过期时间,但是!!!他真的会过期,我后来又仔细看了他的过期机制貌似是用户进来小程序一定时间不点击小程序他就会过期,如果用户一直点击小程序sessionKey就不会过期,对于这个问题的解决办法我们就要交给前端了,当他们调用后端接口之前是要先用微信提供的一个方法检验用户的sessionKey是否过期,如果过期就需要重新调取,保证每一次调接口的sessionKey都是有效的就可以了。这样微信运动的解密就完成啦,并且微信的解密是通用的。

你可能感兴趣的:(java后台微信小程序微信运动之AES解密)