13 changed files with 309 additions and 26 deletions
@ -0,0 +1,141 @@ |
|||||
|
package com.zdxt.common.util; |
||||
|
|
||||
|
import cn.hutool.core.codec.Base64; |
||||
|
import cn.hutool.core.util.IdUtil; |
||||
|
import cn.hutool.core.util.StrUtil; |
||||
|
import cn.hutool.crypto.SecureUtil; |
||||
|
import cn.hutool.crypto.asymmetric.KeyType; |
||||
|
import cn.hutool.crypto.asymmetric.RSA; |
||||
|
import cn.hutool.http.HttpRequest; |
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
|
||||
|
import javax.crypto.Cipher; |
||||
|
import javax.crypto.spec.SecretKeySpec; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
|
||||
|
/** |
||||
|
* 证件号加密工具 |
||||
|
* |
||||
|
* @author joelzzhang |
||||
|
*/ |
||||
|
public class PhoneCardCryptoUtil { |
||||
|
|
||||
|
/** |
||||
|
* 以下字符串为密钥,可以通过配置来传递 |
||||
|
*/ |
||||
|
public static final String OUTER_AES_KEY = "u3BPiZWALItH27e34oO6bw=="; |
||||
|
public static final String INNER_AES_KEY = "ol1hV81iCruo+thxtZGnCg=="; |
||||
|
public static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDADIVdRXNyT5pmGxSUfwEup2Y1YCz7VfibMyyQhkpVP3ByKsoFDjZ30yW5gv70sQbqn/MCthTFqwh3/I/YLfthM3vU7TdlmNfnlKcQ6prxYofLkX8akrhgQVFerb/4DhcbAk5xvx12Dkeh/nzDf5Qw2K3CymRPnr4zN6ZjAL79HwIDAQAB"; |
||||
|
public static final String PRIVATE_KEY = "MIICdAIBADANBgkqhkiG9w0BAQEFAASCAl4wggJaAgEAAoGBAMAMhV1Fc3JPmmYbFJR/AS6nZjVgLPtV+JszLJCGSlU/cHIqygUONnfTJbmC/vSxBuqf8wK2FMWrCHf8j9gt+2Eze9TtN2WY1+eUpxDqmvFih8uRfxqSuGBBUV6tv/gOFxsCTnG/HXYOR6H+fMN/lDDYrcLKZE+evjM3pmMAvv0fAgMBAAECf2rTWPVVrHuC/ywzFz+CmSXAxLNSZbMCH0doYvs0hIrmvtjCjgN1F6P1z2yUpHBEbsetZEwdyQnEf74+WCuBaFIYjmQm/05grIxam/QrGibnV5qNiA0VeCkj6bUy+z5mt3/ithgzjmOiYIgMenjf6ut6RmgRDodgJiFbvSvfskECQQDoqGMNaUV+Y/O9h+l9eOCkSUOjOsL9WDRL34ei/jf7VFFYBZLs2GMzLunDkDz1dHvufDiMPeHUTTN8zIEEpNMVAkEA01Ehf9Np2zUqFQp3SW/fHVsaGM97JsbsTQrsDdUWwZLJTSQ7Yf+yg21GkNa8Mmlsp1OLyS607HV7lPlKO0LsYwJBAN1LTOv0taUCbVRZcj1mPEYHac5Ylh9jRlrkwp7GL3lfOf//TUD6kWCdvrvE9jaCFV9ByIecVLEavV53JkDEhgECQHgR40z0XXOWs8Cc38a0cDwH5b4vNjSEVwQ3roT1jSaUNxlD+xHl7hLLZosp2Gl0ia5RxF2d0mOBJaUyOMGPdy0CQCLBU3995JMoUyLgt2+Riw0PFbdxFEnKGyshAt5Q957/hC6L/V5tQNnh/AM9q23DIUQGb1whhxdIzV12qFSSS34="; |
||||
|
|
||||
|
/** |
||||
|
* 新版 AES/ECB/PKCS5Padding 对称密钥(与 userCrypto.js 保持一致) |
||||
|
* js 中: str1="qwepoiad", str2="sf12vfgi", key = str1+str2 |
||||
|
*/ |
||||
|
private static final String AES_ECB_KEY = "qwepoiadsf12vfgi"; |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
System.out.println("=============== 新版 AES/ECB 加解密示例 ==============="); |
||||
|
// 加密
|
||||
|
String source = "19925235717"; |
||||
|
String encrypted = aesEcbEncrypt(source); |
||||
|
System.out.println(source + " 加密后: " + encrypted); |
||||
|
|
||||
|
// 解密
|
||||
|
String decrypted = aesEcbDecrypt("pm1VDl8q3dfp7irhyhrtiw3amYU1jKdOhpjTqMWv0w="); |
||||
|
System.out.println(encrypted + " 解密后: " + decrypted); |
||||
|
|
||||
|
System.out.println("=============== 批量测试 ==============="); |
||||
|
String[] phones = {"13631554532", "13692276207"}; |
||||
|
for (String phone : phones) { |
||||
|
String enc = aesEcbEncrypt(phone); |
||||
|
System.out.println(phone + " 加密后: " + enc); |
||||
|
System.out.println(enc + " 解密后: " + aesEcbDecrypt(enc)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ======================== 新版 AES/ECB 加解密(与 userCrypto.js 一致) ========================
|
||||
|
|
||||
|
/** |
||||
|
* AES/ECB/PKCS5Padding 加密(Java中PKCS5Padding等价于JS的PKCS7Padding,块大小16时行为一致) |
||||
|
* |
||||
|
* @param content 明文字符串 |
||||
|
* @return Base64 编码的密文 |
||||
|
*/ |
||||
|
public static String aesEcbEncrypt(String content) { |
||||
|
try { |
||||
|
byte[] keyBytes = AES_ECB_KEY.getBytes(StandardCharsets.UTF_8); |
||||
|
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); |
||||
|
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); |
||||
|
cipher.init(Cipher.ENCRYPT_MODE, keySpec); |
||||
|
byte[] encrypted = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); |
||||
|
return Base64.encode(encrypted); |
||||
|
} catch (Exception e) { |
||||
|
throw new RuntimeException("AES ECB 加密失败", e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* AES/ECB/PKCS5Padding 解密(与 userCrypto.js 的 aesDecrypt 对应) |
||||
|
* |
||||
|
* @param encryptedText Base64 编码的密文 |
||||
|
* @return 解密后的明文字符串 |
||||
|
*/ |
||||
|
public static String aesEcbDecrypt(String encryptedText) { |
||||
|
try { |
||||
|
byte[] keyBytes = AES_ECB_KEY.getBytes(StandardCharsets.UTF_8); |
||||
|
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); |
||||
|
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); |
||||
|
cipher.init(Cipher.DECRYPT_MODE, keySpec); |
||||
|
byte[] decrypted = cipher.doFinal(Base64.decode(encryptedText)); |
||||
|
return new String(decrypted, StandardCharsets.UTF_8); |
||||
|
} catch (Exception e) { |
||||
|
throw new RuntimeException("AES ECB 解密失败", e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ======================== 旧版方法(保留兼容) ========================
|
||||
|
|
||||
|
/** |
||||
|
* 证件号通过RSA的公钥加密 |
||||
|
*/ |
||||
|
public static String asymmetricEncryptIdCard(String publicKey, String privateKey, String content) { |
||||
|
RSA rsa = SecureUtil.rsa(privateKey, publicKey); |
||||
|
byte[] encrypt = rsa.encrypt(content, StandardCharsets.UTF_8, KeyType.PublicKey); |
||||
|
return Base64.encode(encrypt); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 证件号通过RSA的私钥解密 |
||||
|
*/ |
||||
|
public static String asymmetricDecryptIdCard(String publicKey, String privateKey, String content) { |
||||
|
RSA rsa = SecureUtil.rsa(privateKey, publicKey); |
||||
|
byte[] decrypt = rsa.decrypt(content, KeyType.PrivateKey); |
||||
|
return StrUtil.str(decrypt, StandardCharsets.UTF_8); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 证件号对称加密后入库(旧版) |
||||
|
*/ |
||||
|
public static String symmetricEncryptIdCard(String key, String content) { |
||||
|
return SecureUtil.aes(SecureUtil.decode(key)).encryptBase64(content); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 证件号对称解密(旧版) |
||||
|
*/ |
||||
|
public static String symmetricDecryptIdCard(String key, String content) { |
||||
|
return SecureUtil.aes(SecureUtil.decode(key)).decryptStr(content); |
||||
|
} |
||||
|
|
||||
|
public static String httpSendPost(String url, String userId, String userName, String appCode) { |
||||
|
HttpRequest request = HttpRequest.post(url) |
||||
|
.header("x-auth-channel", IdUtil.simpleUUID()) |
||||
|
.header("x-auth-app-code", appCode) |
||||
|
.form("userId", userId) |
||||
|
.form("userName", userName); |
||||
|
request.contentType("application/x-www-form-urlencoded"); |
||||
|
JSONObject jsonObject = JSONObject.parseObject(request.execute().body()); |
||||
|
return jsonObject.getString("data"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
package com.zdxt.app.controller.external.company; |
||||
|
|
||||
|
import com.alibaba.fastjson.JSONObject; |
||||
|
import com.zdxt.auth.dto.DeptBean; |
||||
|
import com.zdxt.auth.feign.DeptApi; |
||||
|
import com.zdxt.code.domain.EnterpriseInformation; |
||||
|
import com.zdxt.code.service.ThirdLoginService; |
||||
|
import com.zdxt.common.ZDResponse; |
||||
|
import com.zdxt.common.controller.BaseController; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Controller; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* @Author: kylin |
||||
|
* @Date: 2024/5/1 3:00 下午 |
||||
|
* @Version: 1.0 |
||||
|
* @Desc: TODO |
||||
|
*/ |
||||
|
@Controller |
||||
|
@RequestMapping("/external/user") |
||||
|
public class OutUserController extends BaseController { |
||||
|
|
||||
|
@Autowired private ThirdLoginService thirdLoginService; |
||||
|
|
||||
|
/** |
||||
|
* 新增保存企业信息登记 |
||||
|
*/ |
||||
|
@PostMapping("/addLiqUser") |
||||
|
@ResponseBody |
||||
|
public ZDResponse addLiqUser(@RequestBody JSONObject jsonObject) |
||||
|
{ |
||||
|
Long userId = thirdLoginService.addLiqUser(jsonObject); |
||||
|
return ZDResponse.success("登记成功", userId); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue