RSA+AES加密数据交互,后台java
程序员文章站
2024-03-14 16:04:52
...
-
问题引出,因为项目需要,要对数据进行安全加密,因为安全力度相对比较高,所以就采用了加密措施,以及https协议
-
先解释两点,所有的加密,不论是rsa,还是des,还是md5等等,无非是分为两种,一种是对称加密,一种非对称加密,对称加密自然相同秘钥就可逆了,安全性相对来说比较低.
-
然而,rsa加密的文本长度和秘钥大小有关,2048位秘钥最大可以加密256位文本(不是256位就是128位),而对于大量的数据交互来说,明显不符合要求,AES可以加密较大文本,然而上面说了,安全性不达标.
-
因此鉴于以上两点,决定采用RSA+AES,先说设计思路
- 因为AES可逆,所以,AES的秘钥就不能固定不变,应该每次交互数据秘钥都不一样
- 如果要实现1的条件,则秘钥必须作为额外的数据参数,不断的前后端交互传递
- 如果要实现2,则秘钥必须不能明文,并且秘钥安全性必须极高,否则,加密等于没加密
- 如果要实现3.则rsa是一个很好的选择
- 如果要实现4,则应该有2对rsa秘钥,客户端一对,服务端一对,彼此交互公钥,注意,不能交换私钥,因为有了私钥,则就等于有了公钥,所以,应该是2对秘钥,彼此交换公钥,客户端使用服务端公钥加密,服务端用服务端私钥解密,服务端使用客户端私钥加密,客户端使用服务端公钥解密
-
因此,鉴于以上条件,客户端有公共请求体必须是:
{ key:"使用服务端公钥加密之后的字符串", data:"使用AES加密之后的字符串" }
-
好像说的废话比较多,下面进入正题:
-
RSAUtil
使用npm install jsencrypt --save
,安装插件
import JSEncrypt from 'jsencrypt'
import Constans from '../constants'
export default {
encrypt:function (val) {
var jsencrypt = new JSEncrypt();
jsencrypt.setPublicKey(Constans.RSA.PUBLIC.PREFIX+Constans.RSA.PUBLIC.KEY+Constans.RSA.PUBLIC.SUFFIX);
return jsencrypt.encrypt(val);
},
decrypt:function (val) {
var jsdecrypt = new JSEncrypt();
jsdecrypt.setPrivateKey(Constans.RSA.PRIVATE.PREFIX+Constans.RSA.PRIVATE.KEY+Constans.RSA.PRIVATE.SUFFIX);
return jsdecrypt.decrypt(val);
}
}
- AESUtil
npm install crypto-js --save
const CryptoJS = require('crypto-js');
export default {
encrypt: function (val, key) {
return CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(val),CryptoJS.enc.Utf8.parse(key),{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}).ciphertext.toString().toUpperCase();
},
decrypt: function (val, key,) {
return CryptoJS.AES.decrypt(CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(val)),CryptoJS.enc.Utf8.parse(key),{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}).toString(CryptoJS.enc.Utf8).toString();
}
}
- 因为客户端的所有请求都要进行上述所说的加密处理,所以,一个地方用下,加密下,太麻烦,所以,我进行了请求拦截封装
import axios from 'axios'
import {MessageBox, Message} from 'element-ui'
import store from '@/store'
import {getToken} from '@/utils/auth'
import StringUtil from '@/utils/StringUtil'
import RSAUtil from '@/utils/RSAUtil'
import AESUtil from '@/utils/AESUtil'
const baseUrl = 'http://localhost:8081/';
// create an axios instance
const service = axios.create({
//baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
baseURL: baseUrl,
withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})
// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
var temp = config.data;
// 生成随机的32位字符串,高防java uuid
var key = StringUtil.guid_();
console.log("key : "+key)
// 对key进行rsa加密
var key_ = RSAUtil.encrypt(key);
// 对数据进行aes加密
var data_ = AESUtil.encrypt(JSON.stringify(temp),key);
console.log('data : '+data_)
// 放入要提交的数据中
config.data = {
key: key_,
data: data_
}
console.log(JSON.stringify(config.data))
if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers['ACCESS-TOKEN'] = getToken()
}
console.log(config);
if (config.method.toLocaleUpperCase() == 'POST'||config.method.toLocaleUpperCase()=='PUT'){
config.headers['Content-Type'] = "application/json;charset=utf-8"
}
return config
},
error => {
// do something with request error
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
response => {
const res = response.data
// if the custom code is not 20000, it is judged as an error.
if (res.code !== '0000') {
Message({
message: res.message || 'error',
type: 'error',
duration: 5 * 1000
})
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// to re-login
MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
confirmButtonText: 'Re-Login',
cancelButtonText: 'Cancel',
type: 'warning'
}).then(() => {
store.dispatch('user/resetToken').then(() => {
location.reload()
})
})
}
return Promise.reject(res.message || 'error')
} else {
var key = RSAUtil.decrypt(res.key);
var data = JSON.parse(AESUtil.decrypt(res.data),key);
return data;
}
},
error => {
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
- 如上,我们就可以直接调用传入原始对象了,会统一加密处理,解密也统一处理,在发起请求的时候不用关心加密和解密操作,可以解放许多新手不懂,这样项目进度也比较快
- 以上都是前端代码,后台代码同样会面临每次加解密问题,所以,也做了封装
- RSAUtil(java)
package com.zpecs.blog.utils.rsa;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Properties;
public class RSAUtil {
public static String CLIENT_PUB_KEY = null;
public static String SERVER_PUB_KEY = null;
public static String SERVER_PRI_KEY = null;
static {
try (InputStream is = RSAUtil.class.getClassLoader().getResourceAsStream("rsa.properties")) {
Properties properties = new Properties();
properties.load(is);
CLIENT_PUB_KEY = properties.getProperty("clintPublicKey");
SERVER_PUB_KEY = properties.getProperty("serverPublicKey");
SERVER_PRI_KEY = properties.getProperty("serverPrivateKey");
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
//private static Map<Integer, String> keyMap = new HashMap<Integer, String>(); //用于封装随机产生的公钥与私钥
public static void main(String[] args) throws Exception {
//生成公钥和私钥
/* String[] keys = genKeyPair();
System.out.println("公钥 : \n"+keys[0]);
System.out.println(keys[0].length());
System.out.println("私钥 : \n"+keys[1]);
System.out.println(keys[1].length());
//加密字符串
String message = "df7238201111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
System.out.println("待加密源 : \n" + message);
//System.out.println();
String s0 = encryptPublic(message, keys[0]);
System.out.println("公钥加密之后 : \n" + s0);
System.out.println("私钥解密之后 : \n" + decryptPrivate(s0, keys[1]));
String s1 = encryptPrivate(message, keys[1]);
System.out.println("私钥加密之后 : \n" + s1);
System.out.println("公钥解密之后 : \n" + decryptPublic(s1, keys[0]));*/
String s = "HlDD2Ca1hh8kc5ldtHqEmWMxT8OZsRAOpwR+4mVbINH/90+1KeEbDUFIf5O/benxOixcwt3CAnRkWJ22HbiOshf2GNhd82kGLIOH0it8FeoWPUnTok56y0JVqL3VxxCSDYWWlHfdNEDHa2lkVADJcWkyrQgqd2ea00+KvBpSvxPLMoLpuBA2c0JKckXgLqIKDR/wqtFgg5jg/kVTm3JJrRyYKLz2e0p/PNlrENNuMw8GG2+DEIRV/KzJPZ69FJKuyVNvInfnYa/ZTLUmzcn9RjP6DgvXShMwJnBuQ2IaTPX0FhhQ8OkEGJMiNIveb8MEsDQGFQ4EZHyIm6HWw9zUDA==";
System.out.println(decryptPrivate(s,
"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCQJ3kWiz3y2fivl3l1dAStBRRwk6vTK6u9oroOD9YIqrSccmh94Ou+Wbvz8TQBwtSGPZcNSJhqQUSPr75HygBJRhRGrNJSO8C6M4NuYKsGz8YP3EcTlZndA55Vfrx0uZdEmOYXUtUtb3IbirWS2WiIhJItu6mSWiJyzVri2sVTthhlB+qaRVoLrki0K7XCHBtFyKQHf22rB5d+dAP3jg3h9NoG+CmOV9h2TT2ujTH5HPJ/AU62ijasSIwlM6z7Agi2F52E8UUGpD5kTIz94H2AlhXtZ/1FPfHQzTo5UoNAEV33QcVuC7A4dxuCUObEKoFZoTlyv7wNSSw8NIfOIugVAgMBAAECggEAPLMiXcfMEhKOkQGrdzWfMmvNK4pC8+yTqIp45artaUDYRHg4X6jyG3kVl6adS5CKhOwySrmi1Dsfb5GFAh2g+Tm1F/11ooLeqIlAcp3p5jhfIhaTJz/7RgFcDowLNutfMtdfK7sJYNRorAhAZNF/Ht0T4IYA5Utm7ghimNud8506etpj84j8VbFeDGX89gOrWHGwKNeGFxaHQaIIZIwuqTtlmoIa2QRTtnVuFwshqTYwO+zCE6kqgivnmoiAMIxWWvxiKOA5LWdqhDoaTCj2P8ae19ZEpYz99Yb7Lx2efcHB1OYPAI/JSORURAEG5VjF0T3UyAv4SlsaCHRqkMGWEQKBgQDbX4Q7pIrRy96Y5+AobjuLPQKfAu5gWZ2XX88ktT7ZjCk79hbWM/aWPmPxbZq4rLHvAnryr9kZASuRgkZwpgbqHyQAhf2mZ5jmCBGSQPnB3wO3F6reyuh4kkkQVDR3o46nS5t2OKI+15SfMCpfwYmYafiL0FB9JiBEjnLyQCXV2wKBgQCoOO+2ZoZS+eLfk0L3wAAqP8sY/rToOVz0R/gVfDpSFOnezLe3XTUrQrLk6COiQuIJ9eRenqa+Mt1cieptaiB/CV0Y68hMAaGz5/gNazLtkfEUczW2NZjKOZwESUxgewA2cRiZb2JNHmlSM5l+miOIoBFpfSwdyDfkfd2b45e0zwKBgAmOfK04es+u6PCSUWKRgsiLDN0ufIH4BXR9uQFpX+aMQ5OYIeCM/PYIm8P9uVrIMywtWHvQC04ajfJV0YnAwdZbKu9W5vjj1HZY7aMIb5jxhTDpuAjioAP4o3QxpuN7XZCOK6SXzQGd1JymtYHcZYkdPLWiio8ZJRi3d+xzvPI3AoGAYar88ifAYTiYEjqLrRAaiG0VW+O14QY9A88tKDxCGBnwVt0A5UMGdaF6ABEPb0vptOLAvnbaVJ9viiTAqNnvGBK1rJxoZEimO6+4gwH0RZ5wG/FwA+RGW1LrVEnCQFnpm7I6GAtlRWUcvQ8cVTbk3pQgx+BW1svCN7UkDzgqgl0CgYEA2oFUkm5IpHbxvMkklplwI6KvbaF+aXGWgEZNvNnI5dYTcjwc9gJRlXlAwo/g+ImEg5l/drKijQUYcgiKozGIU0cZRBIBO26TUFPmqGmWnIREBrxNyLzDqkRKriM8muu7HWjIflCSzBXIO5BcQxTQWDvnsvSU3U6E/73O7pWZ2zw="));
//System.out.println(encryptPrivate("df723820","MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDV9OCyNmLz9QDqE+vGTQovEByeAldqDdlx9C/1W6d5mdo0pd/rIowlD7tgZgqdbOdytgdd4VTFdAczY8yghUIa/ni2dSZeWrYpST6kRyh/WFOO9Vegq+PJzwo4nnFSHTsSePQ4qX+W5ZBGmxZvn8jaCtXdqhF4gx2LhTKKZ4663qtsgy+WYlP+zCfeh6Czo6l5lYfge4+zhgLR6aUWwO3jTHwQswCOwNlSLaO8KhkXf4TPN23V2aB22FV2fHY9dxZuZPxVqMLyX5ccGkS26PeGUbwnI/7nqvq+J1Wk8/Wi6eEqCz9SU1JflrKcrInSEietUkDACnwvIaYQT/gHdoVTAgMBAAECggEAGUxECS5fEuNkQUkrtp3DV387Mv+p4FNU46Fwzj0RF1K2t0Tprf6+vV8X07UdCjInR6v4QQR0pogqlcv2FQDMqS5vjXtalwt4wHb1niz/v9bswlmGC+xnGaSOW9V4JrJoGq4MimqYOHpaTc7mnzowYH+pe/Uw7aPrKWUNbcoC2VtlYbXrHuL/wUpqffFK1cqtndQ7yPCJzWS71msffRxpZES5ujUw5BL53FbfoczIonpH0r2IYwWIUO5KxtUvupZxXdr1BjUauHHI9vMwkeG3mstVnz6W/q1xA34o7KhHIXW7SMjA+uIIdtn1ElE6To1o6SI6CzqCGDHnH2qOFqaCMQKBgQDwpH7CKEodyGveMpwS2NoK0Yqf9ppGcDhDCMKS26TgVJ4IG1jyRtLXMlzBZ3pJY79BA4rWSbY0B3D1SDmcJJP1ixOBgFDznnIdv9dUUM4C61TDFXOkQSgcfEeAThYLpX0/OLjj7+SEhYbnp58mF96S1G0wF218IvV7LPfAK7KqCwKBgQDjnGYwJ1wDuRiSmrcZdtXL9zxwvsG2ODgA5U0Q98BcKWuvsM2/FWvYuBcN+5tIAzToJs9ohKRJss+ugZSZSXpv7zvYScrg4ph9mQsn/zhXiGx1GiOkxorOohqf5Gvx7Wf7nqm/EVPmog0FMQlnkR0JBMu4XrmywHxnGmTjNkxm2QKBgQDfKw5LLWYe3MH8nN7VM7pykgWHeAF3FZd3w2X/ICd1y8OLLSF9/mSGIjSXQEnOSe0SdCCLvmx1L/l33/VdcyasbsA2NzPb2rNmF4Wwsgd7+ZbwHLLUP4DdefwtZz1Wq7DNsuL0sIMyy0pjB7a2cyh87vgbw35Lw3f5NajF1UCqJQKBgE9Z90ZScoHZxfdWeP8nruGtECU+W8prTxsA1h1UQnve9OwLd69miHLFu0Pks/4nIArPfP+zPpNzA3STOHs4YrcjcHm3QEOmvAMNmBYZpErgBO/ObR7FGR9w5FdaC0gMvHO8nPE/2UBOvrtQnTa+IKFESsG8RIFNGhHX4dRU2c4BAoGAL3TlLNAOtVU7xzQhi0e3wsneUC+08axWVpudZpTkkuAwvGVw+ZbG2tb9nF/oApbgVskNptP9M9K8VPLhgbplB6hfvvI/OrKRpyWib73RK8y98g/tRvd+vQWqfetnCeY63r1deBKnxCdwmBxKr+Svg+RTx7tggIYp6BAJzWVwWP8="));
}
/**
* 随机生成**对
*
* @throws NoSuchAlgorithmException
*/
public static String[] genKeyPair() {
try {
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化**对生成器,**大小为96-1024位
keyPairGen.initialize(2048, new SecureRandom());
// 生成一个**对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
// 得到私钥字符串
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
// 将公钥和私钥保存到Map
return new String[]{publicKeyString, privateKeyString};
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* RSA公钥加密
*
* @param str 加密字符串
* @param publicKey 公钥
* @return 密文
* @throws Exception 加密过程中的异常信息
*/
public static String encryptPublic(String str, String publicKey) {
try {
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
//RSA加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
return outStr;
} catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* RSA私钥解密
*
* @param str 解密字符串
* @param privateKey 私钥
* @return 铭文
* @throws Exception 解密过程中的异常信息
*/
public static String decryptPrivate(String str, String privateKey) {
try {
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(
decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
String outStr = "";
outStr = new String(cipher.doFinal(inputByte));
return outStr;
} catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* rsa 私钥加密
*
* @param str
* @param privateKey
* @return
* @throws Exception
*/
public static String encryptPrivate(String str, String privateKey) {
try {
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(
decoded));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, priKey);
String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
return outStr;
} catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* rsa 公钥解密
*
* @param str
* @param publicKey
* @return
* @throws Exception
*/
public static String decryptPublic(String str, String publicKey) {
try {
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey priKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
String outStr = new String(cipher.doFinal(inputByte));
return outStr;
} catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
- AESUtil(java)
package com.zpecs.blog.utils.aes;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
public class AESUtil {
private static String Algorithm = "AES";
private static String AlgorithmProvider = "AES/ECB/PKCS5Padding"; // 算法/模式/补码方式
public static byte[] encrypt(String src, byte[] key) {
try {
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8")));
return cipherBytes;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static String encrypt(String src, String key) {
try {
return byteToHexString(encrypt(src,key.getBytes("utf-8")));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static byte[] decrypt(String src, byte[] key) {
try {
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] hexBytes = hexStringToBytes(src);
byte[] plainBytes = cipher.doFinal(hexBytes);
return plainBytes;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static String decrypt(String src, String key) {
try {
return new String(decrypt(src, key.getBytes("utf-8")),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 将byte转换为16进制字符串
*
* @param src
* @return
*/
public static String byteToHexString(byte[] src) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xff;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
sb.append("0");
}
sb.append(hv);
}
return sb.toString();
}
/**
* 将16进制字符串装换为byte数组
*
* @param hexString
* @return
*/
public static byte[] hexStringToBytes(String hexString) {
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] b = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
b[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return b;
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
}
- 基本请求体,为了解决每次解密问题
package com.zpecs.blog.pojo.req;
import com.alibaba.fastjson.JSON;
import com.zpecs.blog.utils.aes.AESUtil;
import com.zpecs.blog.utils.rsa.RSAUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class BaseRequest implements Serializable {
private String key;
private String data;
// 获取解密之后的对象
public<T> T getObj(Class<T> clazz){
// 对key rsa解密
String key_ = RSAUtil.decryptPrivate(key, RSAUtil.SERVER_PRI_KEY);
// 对数据进行aes解密
String data_ = AESUtil.decrypt(data, key_);
// 进行json解析
return JSON.parseObject(data_,clazz);
}
}
- 基本响应体
package com.zpecs.blog.pojo.res;
import com.alibaba.fastjson.JSON;
import com.zpecs.blog.exceptions.BaseException;
import com.zpecs.blog.utils.StringUtil;
import com.zpecs.blog.utils.aes.AESUtil;
import com.zpecs.blog.utils.rsa.RSAUtil;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.UUID;
@Getter
@Setter
public class BaseResponse implements Serializable {
private String code;
private String msg;
private String data;
private String key;
private BaseResponse() {
}
public static BaseResponse success() {
BaseResponse response = new BaseResponse();
response.code = BaseException.ExceptionType.SUCCESS.getCode();
response.msg = BaseException.ExceptionType.SUCCESS.getMsg();
return response;
}
public static BaseResponse success(Object data) {
BaseResponse response = success();
// aes key
String key = UUID.randomUUID().toString().replaceAll("-", "");
// 对key进行rsa加密
response.key = RSAUtil.encryptPublic(key, RSAUtil.CLIENT_PUB_KEY);
// 对内容进行aes加密
response.data = AESUtil.encrypt(JSON.toJSONString(data), key);
return response;
}
public static BaseResponse error(BaseException.ExceptionType exceptionType) {
BaseResponse baseResponse = new BaseResponse();
baseResponse.code = exceptionType.getCode();
baseResponse.msg = exceptionType.getMsg();
return baseResponse;
}
public static BaseResponse error(BaseException.ExceptionType exceptionType, Object data) {
BaseResponse baseException = error(exceptionType);
String key = StringUtil.uuid();
// 对key进行rsa加密
baseException.key = RSAUtil.encryptPublic(key, RSAUtil.CLIENT_PUB_KEY);
// 对内容进行aes加密
baseException.data = AESUtil.encrypt(JSON.toJSONString(data), key);
return baseException;
}
}
- 如此,基本就完美解决客户要求,并且,对于新手开发来说没有太大压力,因为整个开发过程和之前不加密的开发过程几乎一模一样
- 例子:
1.前端请求:
export function login(data) {
return request({
url: 'api/account/login',
method: 'post',
data
})
}
login({username:'zhangsan',password:'123'}).then(data => {
console.log(data);
_v.loading = false;
},error => {
_v.loading = false;
})
- 后台接口
@RestController
@RequestMapping("api/account")
public class AccountController {
@Reference
private UserService userService;
@Autowired
private RedisTemplate redisTemplate;
@PostMapping(value = "login",consumes = "application/json")
public BaseResponse login(@RequestBody BaseRequest request) {
String accessToken = StringUtil.uuid();
UserModel userModel = userService.login(request.getObj(UserModel.class));
redisTemplate.opsForValue().set(Constans.RedisKey.ACCESS_TOKEN_PREFIX + userModel.getUsername(), accessToken);
return BaseResponse.success(new HashMap() {{
this.put("ACCESS-TOKEN", accessToken);
this.put("currentUser", userModel);
}});
}
}
- 代码入侵性极小,并且就算突然移除加密,完全不影响已有代码逻辑
上一篇: 工程效率如何为研发赋能 博客分类: 奇文分享 工程效率如何为研发赋能
下一篇: 简单对称加解密(一)