您的位置:首页 > 新闻 > 热点要闻 > 软件测试报告_江西赣州公司_营销方法有哪几种_优化关键词具体要怎么做

软件测试报告_江西赣州公司_营销方法有哪几种_优化关键词具体要怎么做

2025/3/14 21:00:31 来源:https://blog.csdn.net/qq_54421200/article/details/146234946  浏览:    关键词:软件测试报告_江西赣州公司_营销方法有哪几种_优化关键词具体要怎么做
软件测试报告_江西赣州公司_营销方法有哪几种_优化关键词具体要怎么做

目录

一、后端实现

 二、前端实现(Vue2)

三、补充

 1.增强安全措施

 四、最后说明


步骤大致如下:

  1. 后端生成RSA密钥对,提供公钥接口。
  2. 前端请求公钥,生成随机AES密钥和IV。
  3. 用RSA公钥加密AES密钥,用AES密钥加密数据。
  4. 发送包含加密后的AES密钥和数据的请求体。
  5. 后端用RSA私钥解密AES密钥,再用AES密钥解密数据。
  6. 使用注解和拦截器自动处理解密过程。

        需要确保每个步骤都正确实现,特别是加密模式、填充方式以及编码解码的一致性,避免因配置不同导致解密失败。有什么没加入的在评论区艾特我,我进行补充

一、后端实现

  • 新增AES工具类:
public class AesUtils {public static String encrypt(String data, String key, String iv) throws Exception {SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");IvParameterSpec ivSpec = new IvParameterSpec(Base64.getDecoder().decode(iv));Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);byte[] encrypted = cipher.doFinal(data.getBytes());return Base64.getEncoder().encodeToString(encrypted);}public static String decrypt(String data, String key, String iv) throws Exception {byte[] keyBytes = Base64.getDecoder().decode(key);byte[] ivBytes = Base64.getDecoder().decode(iv);byte[] encryptedBytes = Base64.getDecoder().decode(data);Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);return new String(cipher.doFinal(encryptedBytes));}
}
  •  修改请求处理切面:
/*** 解密切面*/
@ControllerAdvice
public class DecryptAdvice extends RequestBodyAdviceAdapter {private final RsaKeyManager keyManager;public DecryptAdvice(RsaKeyManager keyManager) {this.keyManager = keyManager;}@Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {return methodParameter.hasMethodAnnotation(NeedDecrypt.class);}@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage,MethodParameter parameter,Type targetType,Class<? extends HttpMessageConverter<?>> converterType) throws IOException {try {String encryptedBody = new String(inputMessage.getBody().readAllBytes());JSONObject json = JSONObject.parseObject(encryptedBody);// 解密 AES 密钥String encryptedAesKey = json.getString("encryptedKey");String aesKey = RsaUtils.decryptByPrivateKey(encryptedAesKey, keyManager.getPrivateKey());// 解密数据String decryptedData = AesUtils.decrypt(json.getString("encryptedData"),aesKey,json.getString("iv"));return new DecryptedHttpInputMessage(new ByteArrayInputStream(decryptedData.getBytes()),inputMessage.getHeaders());} catch (Exception e) {throw new RuntimeException("解密失败", e);}}
}
  • 新增注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NeedDecrypt {
}
  • 新增公私钥管理类
/*** 生成RSA*/
public class RsaKeyManager {Logger log = LoggerFactory.getLogger(RsaKeyManager.class);private final RedisService redisService;// Redis 键名private static final String PUBLIC_KEY = "rsa:public";private static final String PRIVATE_KEY = "rsa:private";public RsaKeyManager(RedisService redisService) {this.redisService = redisService;}/*** 初始化密钥(全局唯一)*/@PostConstructpublic void initKeyPair() throws Exception {// 使用 SETNX 原子操作确保只有一个服务生成密钥Boolean isAbsent = redisService.setIfAbsent(PUBLIC_KEY, "");if (Boolean.TRUE.equals(isAbsent)) {KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");generator.initialize(2048);KeyPair keyPair = generator.generateKeyPair();// 存储密钥redisService.set(PUBLIC_KEY,Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()));redisService.set(PRIVATE_KEY,Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()));log.info("---------------------------初始化RSA秘钥---------------------------");}}/*** 获取公钥*/public String getPublicKey() {Object publicKey = redisService.get(PUBLIC_KEY);return Objects.isNull(publicKey)?null:publicKey.toString();}/*** 获取私钥*/public String getPrivateKey() {Object privateKey = redisService.get(PRIVATE_KEY);return Objects.isNull(privateKey)?null:privateKey.toString();}
}
  • 新增DecryptedHttpInputMessage
public class DecryptedHttpInputMessage implements HttpInputMessage {private final InputStream body;private final HttpHeaders headers;public DecryptedHttpInputMessage(InputStream body, HttpHeaders headers) {this.body = body;this.headers = headers;}@Overridepublic InputStream getBody() throws IOException {return this.body;}@Overridepublic HttpHeaders getHeaders() {return this.headers;}
}
  • 新增获取公钥接口 
@RestController
@RequestMapping("/rsa")
public class RSAController {@Autowiredprivate RsaKeyManager rsaKeyManager;/*** 获取公钥* @return 结果*/@GetMapping("/publicKey")public R<String> getPublicKey() {String publicKey = rsaKeyManager.getPublicKey();return R.ok(publicKey);}}

 二、前端实现(Vue2)

  • 安装新依赖:
npm install crypto-js
  • 加密工具(src/utils/crypto.js): 

        getPublicKey 为请求公钥的接口,需要按照自己请求方式去获取 

import JSEncrypt from 'jsencrypt'
import CryptoJS from 'crypto-js'
import { getPublicKey } from '../request/api/auth'// 初始化公钥
export async function initPublicKey() { try {const res = await getPublicKey()return formatPublicKey(res.data)} catch (error) {console.error('公钥获取失败:', error)throw new Error('安全模块初始化失败')}
}// 生成AES密钥
export function generateAesKey() {const key = CryptoJS.lib.WordArray.random(32)const iv = CryptoJS.lib.WordArray.random(16)return {key: CryptoJS.enc.Base64.stringify(key),iv: CryptoJS.enc.Base64.stringify(iv)}
}// AES加密
export function aesEncrypt(data, key, iv) {const encrypted = CryptoJS.AES.encrypt(JSON.stringify(data),CryptoJS.enc.Base64.parse(key), { iv: CryptoJS.enc.Base64.parse(iv),mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7})return encrypted.toString()
}// 格式化公钥
function formatPublicKey(rawKey) {return `-----BEGIN PUBLIC KEY-----\n${wrapKey(rawKey)}\n-----END PUBLIC KEY-----`
}// 每64字符换行
function wrapKey(key) {return key.match(/.{1,64}/g).join('\n')
}
  • 修改请求拦截器: 
service.interceptors.request.use(async config => {if (config.needEncrypt) {await initPublicKey(service)// 生成AES密钥const aes = generateAesKey()// 加密数据const encryptedData = aesEncrypt(config.data, aes.key, aes.iv)// 加密AES密钥const encryptor = new JSEncrypt()encryptor.setPublicKey(publicKey)const encryptedKey = encryptor.encrypt(aes.key)// 构造请求体config.data = {encryptedKey: encryptedKey,encryptedData: encryptedData,iv: aes.iv}}return config
})

三、补充

  • 后端需要加密的接口示例 
@PostMapping("/secure-data")
@NeedDecrypt
public String handleSecureData(@RequestBody Map<String, Object> decryptedData) {return "Decrypted data: " + decryptedData.toString();
}
  • 请求结构体 
{"encryptedKey": "RSA加密后的AES密钥","encryptedData": "AES加密后的数据","iv": "Base64编码的IV"
}

 1.增强安全措施

  • 密钥时效性

// 前端每次请求生成新密钥
const aes = generateAesKey()
  • 完整性校验

// 后端解密后可添加HMAC校验
String hmac = json.getString("hmac");
if(!verifyHMAC(decryptedData, hmac, aesKey)) {throw new SecurityException("Data tampered");
}
  • 防御重放攻击

// 前端添加时间戳和随机数
config.data.timestamp = Date.now()
config.data.nonce = Math.random().toString(36).substr(2)

 四、最后说明

该方案相比纯RSA加密有以下优势:

  1. 性能提升:AES加密大数据效率比RSA高1000倍以上

  2. 前向安全性:每次请求使用不同AES密钥

  3. 安全性增强:CBC模式+随机IV避免模式分析攻击

实际部署时需注意:

  1. 使用HTTPS传输加密后的数据

  2. 定期轮换RSA密钥对

  3. 对敏感接口添加频率限制

  4. 在网关层实现解密拦截器(而非应用层)

 

 

 

 

 

 

 

     

     

     

     

     

     

      版权声明:

      本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

      我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com