用户信息(密码、手机号)使用“AES、BASE64”加密、解密。---------- 经营项目

博客介绍了在工具包中添加加密类、解密类和工具类,同时提到使用注解进行序列化和反序列化操作,这些内容与信息技术中的数据处理和安全相关。

1.在工具包下加入加密类、解密类、工具类。
加密

/**
 * 对敏感信息例如身份证、手机号进行加密
 *
 * @Author: qinencheng
 * @Date: 2021/04/07
 */
public class SensitiveInfoDeserializer extends JsonDeserializer {

    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException, JsonProcessingException {
        String plainSensitiveInfo = jsonParser.getText();
        try {
            String cipherSensitiveInfo = SensitiveInfoUtil.encryptSensitiveInfoBak(plainSensitiveInfo);
            return cipherSensitiveInfo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

在这里插入代码片

解密

/** 对敏感信息例如身份证、手机号进行解密
 * @Author: qinencheng
 * @Date: 20210407
 */
public class SensitiveInfoSerializer extends JsonSerializer {

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        String cipherSensitiveInfo = String.valueOf(value);
        try {
            String plainSensitiveInfo = SensitiveInfoUtil.decryptSensitiveInfoBak(cipherSensitiveInfo);
            gen.writeString(plainSensitiveInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

工具类

public class SensitiveInfoUtil {

    private static final Logger logger = LoggerFactory.getLogger(SensitiveInfoUtil.class);

    private static final String DEFAULT_KEY = Constant.DB_SENSITIVE_INFORMATION_KEY;

    /**
     * 加密敏感信息
     * @param originalInfo 原始待加密敏感信息字符串
     * @return 加密后的信息字符串
     */
    public static String encryptSensitiveInfo(String originalInfo) throws Exception {
        return originalInfo;
    }

    /**
     * 解密敏感信息
     * @param encryptResult 被加密的敏感信息字符串
     * @return 解密后的敏感信息
     */
    public static String decryptSensitiveInfo(String encryptResult) throws Exception {
        return encryptResult;
    }

    /**
     * 加密敏感信息
     * @param originalInfo 原始待加密敏感信息字符串
     * @return 加密后的信息字符串
     */
    public static String encryptSensitiveInfoBak(String originalInfo) throws Exception {

        String encryptResult = null;

        if(StringUtils.isBlank(originalInfo))
            return originalInfo;
        byte[] raw = DEFAULT_KEY.getBytes("utf-8");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(originalInfo.getBytes("utf-8"));
        encryptResult = new BASE64Encoder().encode(encrypted);

        return encryptResult;
    }

    /**
     * 解密敏感信息
     * @param encryptResult 被加密的敏感信息字符串
     * @return 解密后的敏感信息
     */
    public static String decryptSensitiveInfoBak(String encryptResult) throws Exception {

        String originalInfo = null;

        if(null == encryptResult || StringUtils.isBlank(encryptResult) || StringUtils.equals("null", encryptResult))
            return "";
        if(StringUtils.length(encryptResult) <= 20 || encryptResult.contains("_") || isContainChinese(encryptResult))
            return encryptResult;
        byte[] raw = DEFAULT_KEY.getBytes("utf-8");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] encrypted1 = new BASE64Decoder().decodeBuffer(encryptResult);//先用base64解密
        byte[] original = cipher.doFinal(encrypted1);
        originalInfo = new String(original, "utf-8");

        return originalInfo;
    }

    private static boolean isContainChinese(String str) {
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        if (m.find()) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws Exception {

        // 需要加密的字串
       String cSrc = "110108196607016033";
//        System.out.println(cSrc);
//        // 加密
//        String enString = SensitiveInfoUtil.encryptSensitiveInfo(cSrc);
//        System.out.println("加密后的字串是:" + enString);
        String enString = SensitiveInfoUtil.encryptSensitiveInfoBak(cSrc);
        System.out.println("加密后的字串是:" + enString);
//
//        // 解密
        String DeString = SensitiveInfoUtil.decryptSensitiveInfoBak("R7AdqCy0Pw/RZxjSObKuaI9EJ4rkC0P/1AcRZ2Rek+E=");
        System.out.println("解密后的字串是:" + DeString);
//
//        //String string = "130302198611121421";
//        DeString = SensitiveInfoUtil.encryptSensitiveInfo(DeString);
//        System.out.println("解密后的字串是:" + DeString);
//
//        String string = "中国铁路北京局集团有限公司京沪高速铁路天津西站工程建设指挥部(洗涤)基础岗位";
//        DeString = SensitiveInfoUtil.encryptSensitiveInfo(string);
//        System.out.println("解密后的字串是:" + DeString);


//        String string1 = "sr/0QyAxajVXdqR7/Pev2ncqrdyRUVleSETFuR7ItQA=";
//        string1 = SensitiveInfoUtil.decryptSensitiveInfo(string1);
//        System.out.println("解密后的字串是:" + string1);

        /*string = "admin123";
        DeString = SensitiveInfoUtil.encryptSensitiveInfo(string);
        System.out.println("解密后的字串是:" + DeString);*/
    }
}

2.使用注解序列化,反序列化。

  /**
     * 手机号
     */
    @TableField(value = "TEL")
    @ApiModelProperty(value = "手机号")
    @JsonDeserialize(using = SensitiveInfoDeserializer.class)
    @JsonSerialize(using = SensitiveInfoSerializer.class)
    private String tel;
<think> 我们参考引用内容,结合Uni-App开发微信小程序获取手机号的流程,需要注意以下几点: 1. 获取手机号需要用户主动触发(绑定在按钮上) 2. 需要先调用登录接口(wx.login)获取code,然后后端根据code获取session_key 3. 当用户点击获取手机号按钮时,会触发事件,事件回调中可以获取到加密的数据(encryptedData)和初始向量(iv) 4. 将加密数据、iv和登录时获取的code(或者后端返回的session_key)传递给后端进行解密(或者前端自己解密,但一般建议后端解密) 5. 如果session_key过期,需要重新登录获取新的session_key 根据引用[1]的提示,如果登录后过了一段时间再获取手机号,可能会因为session_key过期而解密失败,所以可以在每次获取手机号前重新登录获取新的session_key。 下面我们提供两种方式的完整代码: 方式一:前端传递加密数据和iv给后端,由后端解密(推荐) 方式二:前端自己解密(需要在前端存储session_key,不太安全,一般不推荐) 由于引用[1]提到个人小程序不支持获取手机号,所以请确保你的小程序是企业或个体工商户主体。 我们主要讲解方式一(后端解密)的完整代码。 步骤: 1. 用户点击按钮触发获取手机号事件(需要将button组件的open-type设置为"getPhoneNumber") 2. 在事件处理函数中,获取到加密数据和iv,同时重新登录获取新的code(避免session_key过期) 3. 将code、encryptedData、iv发送给后端,后端用code换取session_key,然后用session_key解密手机号 4. 后端返回手机号 注意:在uni-app中,我们可以使用uni.login()代替wx.login()使用uni.getUserProfile()来获取用户信息(但获取手机号不需要这个),获取手机号是单独的button事件。 代码结构如下: 模板部分(pages/index/index.vue): ``` <template> <view> <button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取手机号</button> </view> </template> ``` 脚本部分: ``` <script> export default { methods: { async getPhoneNumber(e) { // 注意:从基础库2.21.2开始,对获取手机号的接口进行了安全升级,需要用户主动触发按钮,并且返回的加密数据需要传递code给后端 // 如果用户拒绝,则e.detail.code为'拒绝的code',具体看微信文档 if (e.detail.errMsg === 'getPhoneNumber:fail user deny') { uni.showToast({ title: '用户拒绝授权', icon: 'none' }); return; } // 用户同意 try { // 1. 先调用登录,获取新的code(防止之前的session_key过期) const loginRes = await uni.login({ provider: 'weixin' }); const code = loginRes.code; // 2. 获取到事件对象中的加密数据和iv const { encryptedData, iv } = e.detail; // 3. 发送给后端解密 const res = await uni.request({ url: '你的后端接口地址', method: 'POST', data: { code: code, encryptedData: encryptedData, iv: iv } }); // 4. 后端返回的数据中应该包含手机号 if (res.data.code === 200) { const phoneNumber = res.data.phone; // 获取手机号成功,进行后续操作 console.log(phoneNumber); } else { uni.showToast({ title: '获取手机号失败:' + res.data.msg, icon: 'none' }); } } catch (error) { uni.showToast({ title: '请求失败:' + error.message, icon: 'none' }); } } } } </script> ``` 注意:上面代码中,后端接口需要接收三个参数:code、encryptedData、iv,然后进行解密操作。 后端解密步骤(供参考,非前端代码): 1. 使用code调用微信接口(jscode2session)获取session_key和openid 2. 使用session_key、encryptedData、iv进行解密(对称解密) 3. 解密后得到一个json字符串,其中包含手机号 解密后的数据结构示例: ``` { "phoneNumber": "135xxxxxx", "purePhoneNumber": "135xxxxxx", "countryCode": "86", "watermark": { "appid": "小程序appid", "timestamp": 时间戳 } } ``` 另外,引用[1]中提到,如果解密失败,可能是因为session_key过期,所以我们在每次获取手机号前都重新登录获取一个新的code,然后用这个code去后端换取新的session_key,这样就能保证session_key是最新的。 关于引用[2],它是获取用户信息的,与获取手机号是两个不同的接口,这里我们不需要用到。 总结:以上就是在uni-app微信小程序中获取用户手机号的完整前端代码。后端解密部分需要开发者自行实现(可以使用微信官方提供的解密方式)。 注意:由于微信小程序版本更新,请务必参考最新的官方文档。 相关问题: 1. 如何解决微信小程序获取手机号时session_key过期的问题? 2. 在uni-app中,如何实现微信登录获取用户信息? 3. 后端如何解密微信小程序获取的手机号加密数据? </think> 以下是 Uni-App 微信小程序获取用户手机号的完整代码实现及关键步骤说明: ### 完整代码示例 ```vue <template> <view> <!-- 1. 触发按钮(必须设置 open-type) --> <button open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber" > 获取手机号 </button> </view> </template> <script> export default { methods: { async onGetPhoneNumber(e) { // 2. 检查用户是否授权 if (e.detail.errMsg.includes('deny')) { uni.showToast({ title: '用户拒绝授权', icon: 'none' }); return; } try { // 3. 先执行登录获取最新 session_key const [loginRes] = await uni.login({ provider: 'weixin' }); if (!loginRes.code) throw new Error('登录失败'); // 4. 获取加密数据 const { encryptedData, iv } = e.detail; // 5. 发送到后端解密 const { data } = await uni.request({ url: 'https://your-api.com/decrypt-phone', // 替换为实际API method: 'POST', data: { code: loginRes.code, // 登录凭证 encryptedData, // 加密手机号数据 iv // 解密初始向量 } }); // 6. 获取解密后的手机号 if (data.success) { console.log('手机号:', data.phoneNumber); uni.showToast({ title: `手机号: ${data.phoneNumber}` }); } else { throw new Error(data.message || '解密失败'); } } catch (error) { uni.showToast({ title: '获取失败: ' + error.message, icon: 'none' }); } } } } </script> ``` ### 关键实现说明 1. **前端流程** - 使用 `open-type="getPhoneNumber"` 的按钮触发授权 - 通过 `@getphonenumber` 事件接收加密数据 - 每次操作前调用 `uni.login()` 获取最新 `session_key`(防止过期) -加密数据和登录凭证发送给后端解密[^1] 2. **后端解密要求**(需自行实现) ```javascript // 示例解密步骤 (Node.js) const { code, encryptedData, iv } = req.body; const { session_key } = await wxApi.jscode2session(code); // 微信API换取session_key // 使用AES解密 const decryptData = (encryptedData, iv, sessionKey) => { const decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv); return JSON.parse(decipher.update(encryptedData, 'base64', 'utf8') + decipher.final('utf8')); }; const phoneData = decryptData(encryptedData, iv, session_key); // 返回结果: { countryCode: "86", phoneNumber: "13800138000" } ``` 3. **注意事项** - ✅ **主体限制**:个人小程序不支持获取手机号(需企业主体)[^1] - ✅ **登录前置**:必须完成 `uni.login()` 获取有效 `code` - ✅ **时效性**:`session_key` 有效期约30分钟,需每次重新获取[^1] - ❌ **前端解密**:不推荐(需暴露 `session_key` 不安全) - 🔒 **安全要求**:后端需验证 `appId` 防止数据篡改 ### 调试建议 1. 使用**微信开发者工具**真机调试 2. 检查网络请求是否正常发送 3. 后端解密失败时返回详细错误码: - `-41001`: session_key 过期 - `-41003`: 非法 session_key - `-43002`: 解密失败
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值