美文网首页小程序实用UI及常见问题解决
java获取微信openId和解密小程序用户信息

java获取微信openId和解密小程序用户信息

作者: Frankeen | 来源:发表于2019-08-15 15:35 被阅读1次
    小程序获取登录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

    相关文章

      网友评论

        本文标题:java获取微信openId和解密小程序用户信息

        本文链接:https://www.haomeiwen.com/subject/cqyzjctx.html