微信小程序登录 后端java

2021/4/30 14:25:31

本文主要是介绍微信小程序登录 后端java,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

微信小程序登录 后端java

    • 小程序前端
    • java 后端

微信小程序对于2021年4月1日还未发布的小程序,前端根据wx.getUser得到的数据已无法解析到用户信息。更改前端调用接口为wx.getUserProFile,需要用户授权后才可获得用户相关信息。

小程序前端

小程序前端调用wx.login接口可获得code
小程序前端调用wx.getUserProFile 可获得encryptedData 和 iv

java 后端

java后端在获取到对应的数据后访问:https://api.weixin.qq.com/sns/jscode2session换取openid和session_key(用于对数据解码),然后对数据进行解码。
代码如下:

@RequestMapping(value = "login.html")
    public ResponseVO login(HttpServletRequest request) {
        String encryptedData = request.getParameter("encryptedData");
        String iv = request.getParameter("iv");
        String code = request.getParameter("code");
        if (StringTool.checkedString(encryptedData, iv, code)) {
            return ResponseVO.failure("请同意微信读取相关信息!");
        }
        String appid = "小程序appId";
        String appSecret = "小程序对应的appSecret";
        String apiUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
        String responseBody = HttpsUtil.doGet(apiUrl);
        Map<String, String> jsonObject = new Gson().fromJson(responseBody, Map.class);
        if (!StringTool.checkedString(jsonObject.get("openid")) && !StringTool.checkedString(jsonObject.get("session_key"))) {
            //查询用户是否存在
            PlayerInfo playerInfo = playerInfoService.getMemberByUId(jsonObject.get("openid"));
            if (playerInfo == null) {
                //解密获取用户信息
                JSONObject userInfoJSON = WechatGetUserInfoUtil.getUserInfo(encryptedData, jsonObject.get("session_key"), iv);
                if (userInfoJSON != null) {
                    playerInfo = new PlayerInfo();
                    playerInfo.setUNickName(userInfoJSON.get("nickName").toString());//昵称
                    playerInfo.setUId(jsonObject.get("openid"));//openId
                    playerInfo.setUCity(userInfoJSON.get("city").toString());//城市
                    playerInfo.setUSex(Integer.parseInt(userInfoJSON.get("gender").toString()));//性别
                    playerInfo.setULogo(userInfoJSON.get("avatarUrl").toString());//头像
                    playerInfoService.addPlayer(playerInfo);
                }
            }
            return ResponseVO.success(playerInfo);
        }
        return ResponseVO.failure("登录失败!");
    }

HttpsUtil代码如下:

import java.io.IOException;
import java.util.Map;

import com.google.gson.Gson;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;


public class HttpsUtil {

    public static String doGet(String url) {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpGet httpget = new HttpGet(url);
        String jsonObj = null;
        try {
            HttpResponse response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                jsonObj = result;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return jsonObj;
    }

    public static Map<String, Object> doPost(String url, String json) {
        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost(url);
        Map<String, Object> jsonObj = null;
        try {
            StringEntity stringEntity = new StringEntity(json, "UTF-8");
            httpPost.setEntity(stringEntity);
            httpPost.addHeader("Accept", "application/json");
            httpPost.setHeader("content-type", "application/json");

            HttpResponse response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                jsonObj = new Gson().fromJson(result, Map.class);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jsonObj;
    }
}

StringTool代码如下:

/**
 * @version v1.0
 * @Description: TODO(字符串检测工具类)
 * @Author: jyj
 * @Date: 2020/3/25 0025 11:05
 */
public class StringTool {

    /***
     * TODO:检测String是否有为空的情况
     *
     * @param strings
     * @return
     */
    public static boolean checkedString(String... strings) {
        for (String str : strings) {
            if (str == null || str.trim().length() == 0 || str.equals("undefined")) {
                return true;
            }
        }
        return false;
    }
 }

WechatGetUserInfoUtil代码如下:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;

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;
import java.util.Base64;

/**
 * @author lqx
 * @create 2018-08-07 8:30
 */
public class WechatGetUserInfoUtil {
    //日志记录器
    private static final Logger log = LoggerFactory.getLogger(WechatGetUserInfoUtil.class);

    /**
     * 解密用户敏感数据获取用户信息
     *
     * @param sessionKey    数据进行加密签名的密钥
     * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
     * @param iv            加密算法的初始向量
     * @return
     */
    public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
        // 被加密的数据
        byte[] dataByte = Base64Utils.decode(encryptedData.getBytes());
        // 加密秘钥
        byte[] keyByte = Base64Utils.decode(sessionKey.getBytes());
        // 偏移量
        byte[] ivByte = Base64Utils.decode(iv.getBytes());
        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 JSON.parseObject(result);
            }
        } catch (NoSuchAlgorithmException e) {
            log.error(e.getMessage(), e);
        } catch (NoSuchPaddingException e) {
            log.error(e.getMessage(), e);
        } catch (InvalidParameterSpecException e) {
            log.error(e.getMessage(), e);
        } catch (IllegalBlockSizeException e) {
            log.error(e.getMessage(), e);
        } catch (BadPaddingException e) {
            log.error(e.getMessage(), e);
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(), e);
        } catch (InvalidKeyException e) {
            log.error(e.getMessage(), e);
        } catch (InvalidAlgorithmParameterException e) {
            log.error(e.getMessage(), e);
        } catch (NoSuchProviderException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }
 }

以上代码居多,不喜原理,能看到这都是遇到问题才来的。其实原理很简单,就是通过前端传入的encryptedData已经包含了对应的用户数据,只是需要重新通过拿到session_key对数据进行解密而已。如有缺少相关类的请留言。



这篇关于微信小程序登录 后端java的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程