最近开发一个小程序使用的uni-app做了一些封装
首先是前端
import CryptoJS from 'crypto-js';
const secretKey = "secret-key";
// 统一的请求方法
function request(url, method, data) {
// 对称加密,这里选用 AES 算法
const key = CryptoJS.enc.Utf8.parse(secretKey);
const iv = CryptoJS.enc.Utf8.parse(secretKey.substring(0, 16));
const encryptedData = CryptoJS.AES.encrypt(JSON.stringify(data), key, {
iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString();
return uni.request({
url: url,
method: method,
header: {
'content-type': 'application/json'
},
data: encryptedData
}).then(res => {
// 返回解密后的数据
const decryptedData = CryptoJS.AES.decrypt(res.data, key, {
iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
const plaintext = decryptedData.toString(CryptoJS.enc.Utf8);
return Promise.resolve(JSON.parse(plaintext));
}).catch(err => {
console.error('request failed:', err);
return Promise.reject(err);
});
}
export { request };
服务端肯定是在拦截器层进行统一的处理
public class DecryptInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Decrypt decryptedData = method.getAnnotation(Decrypt.class);
if (decryptedData != null) {
// 从请求体中读取密文数据
String encryptedData = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
// 解密数据
String plainText = DecryptUtil .decrypt(encryptedData, "your-secret-key");
// 将明文数据设置到请求体中
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest req = attributes.getRequest();
WrappedHttpServletRequest wrappedReq = new WrappedHttpServletRequest(req);
wrappedReq.setBody(plainText.getBytes());
requestContext.setRequest(wrappedReq);
}
}
return true;
}
}
然后是那几个工具类比如解密的工具类
public class DecryptUtil {
// 解密方法
public static String decrypt(String data, String secretKey) {
try {
byte[] encryptedData = Base64.decodeBase64(data);
byte[] key1 = getSubByteArray(secretKey.getBytes(), 0, 16);
byte[] iv1 = getSubByteArray(secretKey.getBytes(), 0, 16);
SecretKeySpec secretKeySpec = new SecretKeySpec(key1, "AES");
IvParameterSpec iv = new IvParameterSpec(iv1);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);
return new String(cipher.doFinal(encryptedData));
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
// 获取字节数组的子数组
private static byte[] getSubByteArray(byte[] data, int start, int length) {
byte[] result = new byte[length];
System.arraycopy(data, start, result, 0, length);
return result;
}
}
写个测试类
@RestController
@RequestMapping("/api")
public class TestController {
// 加入 Decrypt 注解
@PostMapping(value = "/test", consumes = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity test(@RequestBody @Decrypt User user) {
System.out.println(user);
return ResponseEntity.ok("success");
}
}