Java获取小程序用户信息

Published on with 0 views and 0 comments

流程

  1. 前端调用wx.login接口获取code,然后再调用wx.getUserInfo接口获取用户的信息。
  2. 调用服务器接口,将获取到的code,rawData,signature,encryptedData,iv发送到后端。
  3. 服务器通过code获取openidsession_key
  4. 数据签名校验
  5. 解密用户敏感数据获取用户信息

Java后端实现

数据签名校验

使用sha1加密rawDate+session_key,和signature进行比对

String sha1Hex = DigestUtils.sha1Hex(wxLogin.getRawData() + sessionKey);
boolean signatureResult = sha1Hex.equals(wxLogin.getSignature());

解密用户敏感数据获取用户信息

  • base64解码
    Java 8 内置了 Base64 编码的编码器和解码器。

    	// 被加密的数据
    	byte[] dataByte = Base64.getDecoder().decode(encryptedData);
    	// 加密秘钥
    	byte[] keyByte = Base64.getDecoder().decode(sessionKey);
    	// 偏移量
    	byte[] ivByte = Base64.getDecoder().decode(iv);
    
  • 引用第三方库来进行解密,这里采用的是org.bouncycastle.bcprov-jdk15on,可以使用maven的方式直接引入:

    	<dependency>
    	  <groupId>org.bouncycastle</groupId>
    	  <artifactId>bcprov-jdk15on</artifactId>
    	  <version>1.61</version>
    	</dependency>
    
  • 数据解密

private static final String KEY_ALGORITHM = "AES";
private static final String ALGORITHM_STR = "AES/CBC/PKCS7Padding";
        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(ALGORITHM_STR,"BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, KEY_ALGORITHM);
            AlgorithmParameters parameters = AlgorithmParameters.getInstance(KEY_ALGORITHM);
            parameters.init(new IvParameterSpec(ivByte));
            // 初始化cipher
            cipher.init( Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                return new String(resultByte, StandardCharsets.UTF_8);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }