微信小程序登录unionId的获取和获取手机号的解密算法

本文详细介绍了微信小程序中unionId和手机号的解密算法,包括AES-128-CBC加密方式的实现,以及使用BouncyCastle进行解密的具体步骤。通过对比手机号和unionId的解密差异,帮助开发者理解并正确应用解密算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

微信小程序在调取登录过程中,手机号和unionId的获取都需要揭秘算法,微信多个平台需要unionId进行统一管理时小程序在进行登录时普通的流程unionId获取不到,需要进行解密,后端代码如下
下边是解密算法工具类

-----------------------------------------------------------------------------------------------------------------

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

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;

/**
 * Created by yfs on 2017/2/6.
 * <p>
 * AES-128-CBC 加密方式
 * 注:
 * AES-128-CBC可以自己定义“密钥”和“偏移量“。
 * AES-128是jdk自动生成的“密钥”。
 */
public class AesCbcUtil {


    static {
        //BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * AES解密
     *
     * @param data           //密文,被加密的数据
     * @param key            //秘钥
     * @param iv             //偏移量
     * @param encodingFormat //解密后的结果需要进行的编码
     * @return
     * @throws Exception
     */
    public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {
//        initialize();

        //被加密的数据
        byte[] dataByte = Base64.decodeBase64(data);
        //加密秘钥
        byte[] keyByte = Base64.decodeBase64(key);
        //偏移量
        byte[] ivByte = Base64.decodeBase64(iv);


        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

            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, encodingFormat);
                return result;
            }
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return null;
    }

}

unionId获取可以到此链接进行参考学习https://juejin.im/entry/589944da570c3500624e4554

--------------------------------------------------------------

除了unionId之外 还有就是小程序的解密手机号的算法 一并写出来 解密格式不同其余都差不多

public static String decrypt(String sessionkey, String ivStr, String encDataStr)throws Exception {

    byte[] dataByte = Base64.decode(encDataStr);
    // 加密秘钥
    byte[] keyByte = Base64.decode(sessionkey);
    // 偏移量
    byte[] ivByte = Base64.decode(ivStr);
    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/PKCS5Padding");
        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);
        log.info("参数为"+resultByte);
        if (null != resultByte && resultByte.length > 0) {
            String result = new String(resultByte, "UTF-8");
            return result;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

总结 两种方法都基本相同区别如下

Base64.decode()//此为手机号解密算法

Base64.decodeBase64()//此为unionId解密算法

<think>好的,用户想实现Java后端与微信小程序的授权登录集成,需要指导如何在Java项目中实现接口。首先,我得理清楚微信授权登录的整体流程,根据提供的引用内容,可能涉及获取openid、access_token用户信息等步骤。 用户提供的引用中有几个关键点:[^1]、[^3]、[^5]提到了uniapp前端Java后端的整合,需要确保前后端接口正确对接。[^4]提到获取openid、access_token手机号的步骤,这可能涉及到微信API的调用,比如code换取session_keyopenid,然后获取用户信息。 首先,需要明确微信小程序授权登录的流程。通常流程是:前端获取临时code,传给后端,后端用code向微信服务器请求session_keyopenid,然后生成自定义登录态返回给前端。可能还需要解密用户信息,比如手机号,这时候需要session_key。 然后,用户提到的Java后端需要处理这些步骤。根据引用,需要创建处理微信登录的接口,接收code,调用微信接口,处理返回的数据,并生成自己的token。引用还提到获取手机号,这可能需要在解密时使用session_key,所以后端可能需要保存session_key或者及时处理。 接下来,要确保代码示例的正确性,比如使用Spring Boot框架,创建Controller,处理HTTP请求,使用RestTemplate调用微信API。同时,要注意参数的正确传递,如appid、secret、code等。另外,异常处理也很重要,比如网络请求失败,参数错误等,需要返回相应的错误信息。 用户可能需要了解如何生成自定义的登录态,比如使用JWT生成token,并将openid等信息包含进去,以便后续接口验证。同时,安全方面需要注意,不能将session_key返回给前端,避免泄露。 可能遇到的问题包括code无效、微信接口返回错误,这时候需要根据微信的文档处理错误码。另外,用户信息的解密需要正确使用session_key加密算法,比如AES解密手机号数据。 最后,根据引用内容,用户可能需要完整的示例代码配置步骤,包括前端如何调用接口,后端如何处理返回数据。需要确保代码中的参数如appidsecret是从配置中读取,而不是硬编码,以提高安全性。 总结下来,步骤大致是:配置参数、创建接口处理code、调用微信接口获取openidsession_key、生成自定义token、处理用户信息解密(如手机号)、返回结果给前端。同时,需要处理异常情况安全措施。</think>### Java后端实现微信小程序授权登录的步骤 #### 1. 配置微信开发者信息 在`application.yml`中配置小程序凭证: ```yaml wechat: appid: wx1234567890abcdef secret: 2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d ``` #### 2. 创建登录接口 ```java @RestController @RequestMapping("/api/auth") public class WechatAuthController { @Value("${wechat.appid}") private String appid; @Value("${wechat.secret}") private String secret; @PostMapping("/login") public ResponseEntity<?> wechatLogin(@RequestBody CodeDTO codeDTO) { // 1. 验证code有效性 if (codeDTO.getCode() == null || codeDTO.getCode().isEmpty()) { return ResponseEntity.badRequest().body("无效的授权码"); } // 2. 调用微信接口获取session信息 String url = "https://api.weixin.qq.com/sns/jscode2session?" + "appid=" + appid + "&secret=" + secret + "&js_code=" + codeDTO.getCode() + "&grant_type=authorization_code"; RestTemplate restTemplate = new RestTemplate(); WechatSessionResponse response = restTemplate.getForObject(url, WechatSessionResponse.class); // 3. 处理微信返回数据 if (response.getErrcode() != null) { return ResponseEntity.status(500).body("微信接口错误:" + response.getErrmsg()); } // 4. 生成自定义登录态 String token = JwtUtils.generateToken(response.getOpenid()); return ResponseEntity.ok(new AuthResponse(token, response.getOpenid())); } } ``` #### 3. 定义数据传输对象 ```java @Data public class CodeDTO { private String code; private String encryptedData; // 加密数据(如手机号) private String iv; // 解密向量 } @Data public class WechatSessionResponse { private String openid; private String session_key; private String unionid; private Integer errcode; private String errmsg; } ``` #### 4. 实现用户信息解密(示例:手机号解密) ```java public String decryptPhoneNumber(String encryptedData, String sessionKey, String iv) { try { byte[] key = Base64.getDecoder().decode(sessionKey); byte[] ivBytes = Base64.getDecoder().decode(iv); byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); byte[] result = cipher.doFinal(encryptedBytes); return new String(result); } catch (Exception e) { throw new RuntimeException("解密失败", e); } } ``` #### 5. 安全建议 - 使用HTTPS保证通信安全 - 限制session_key的有效期(建议不超过24小时) - 敏感操作需进行二次验证 - 定期更新微信密钥 ### 典型调用流程 1. 小程序端调用`wx.login()`获取code 2. 将code发送到Java后端`/api/auth/login`接口 3. 后端通过code换取openidsession_key 4. 生成JWT返回给小程序 5. (可选)解密手机号等敏感信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值