微信登录授权, 并且解密加密内容获取手机号和地区

所使用的的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.3.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.13</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <version>2.3.3.RELEASE</version>
    </dependency>
    <!--fastjson-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.72</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.59</version>
    </dependency>

</dependencies>

1.微信登录授权, 获取openId

    @ApiOperation(value = "用户登录,三个参数为code, avatarUrl, nickName")
    @PostMapping("/login")
    public ResultBean getWxCode(@RequestParam(value = "code") String code, @RequestParam(value = "wxName") String wxName,
                                @RequestParam(value = "userAvatar") String userAvatar,
                                HttpServletRequest request) {
        // 配置请求参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", WxLoginCommons.WX_LOGIN_APPID);
        param.put("secret", WxLoginCommons.WX_LOGIN_SECRET);
        param.put("js_code", code);
        param.put("grant_type", WxLoginCommons.WX_LOGIN_GRANT_TYPE);
        // 发送请求
        String wxResult = HttpClientUtil.doGet(WxLoginCommons.WX_LOGIN_URL, param);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);
        // 获取参数返回的
        if (!jsonObject.containsKey("openid")) {
            System.out.println("没有openid");
            return ResultBean.fail(ErrorCodeEnum.AuthorizationFail.getCode(), ErrorCodeEnum.AuthorizationFail.getMsg());
        }
        String session_key = jsonObject.get("session_key").toString();
        String open_id = jsonObject.get("openid").toString();

 		/** 业务代码省略*/
        
        // 封装返回小程序
        Map<String, String> result = new HashMap<>();
        result.put("sessionId", sessionId);
        result.put("userState", String.valueOf(2));
        result.put("openId", open_id);

        return ResultBean.success(200, "新用户创建成功", result);
    }

HttpClientUtil.java

package com.wx.utils;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class HttpClientUtil {

    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);
    }

    public static String doPost(String url, Map<String, String> param) {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }

    public static String doPost(String url) {
        return doPost(url, null);
    }

    public static String doPostJson(String url, String json) {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }
}

2. 解密加密内容

小程序代码: 通过绑定的按钮触发, 用户点击获取手机号并且同意后, 即可通过以下函数,输出iv 和encryptedData, 通过解密函数, 得到加密内容

getPhoneNumber: function(e) { 
    console.log(e.detail.errMsg) 
    console.log("---------")
    console.log(e.detail.iv) 
    console.log(e.detail.encryptedData) 
    if (e.detail.errMsg == 'getPhoneNumber:fail user deny'){
      wx.showModal({
          title: '提示',
          showCancel: false,
          content: '未授权',
          success: function (res) { }
      })
    } else {
      wx.showModal({
          title: '提示',
          showCancel: false,
          content: '同意授权',
          success: function (res) { }
      })
    }
}

解密脚本(Java版)

public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
    // 被加密的数据
    byte[] dataByte = Base64.decodeBase64(encryptedData);
    // 加密秘钥
    byte[] keyByte = Base64.decodeBase64(sessionKey);
    // 偏移量
    byte[] ivByte = Base64.decodeBase64(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, "UTF-8");
            return JSONObject.parseObject(result);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

注意, 我使用的是springboot, 但是我导入pom依赖后

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.59</version>
</dependency>

, new BouncyCastleProvider()一直爆红, External Libraries也没有对应的文件, 试了很多办法, 最终解决的方法是 : 虽然pom导入依赖 idea中还是不识别这个jar包, 但是maven仓库里面已经下载好了, 通过点击idea右上角Project Structure->Libraries->添加这个jar包, 即可在External Libraries中导入.

posted @ 2021-02-15 22:08  无法手执玫瑰  阅读(1368)  评论(0编辑  收藏  举报