SpringBoot安全策略開發(fā)之集成數(shù)據(jù)傳輸加密
前言
近期在對開發(fā)框架安全策略方面進(jìn)行升級優(yōu)化,提供一些通用場景的解決方案,本文針對前后端數(shù)據(jù)傳輸加密進(jìn)行簡單的分享,處理流程設(shè)計(jì)如下圖所示,本加密方法對原有項(xiàng)目兼容性較好,只需要更換封裝好的加密Ajax請求方法,后端統(tǒng)一攔截判斷是否需要解密即可

生成DESKey
生成的DES加密密鑰一定是8的整數(shù)倍的位數(shù)
function getRandomStr() {
let str = ""
let array = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
];
for (let i = 0; i < 8; i++) {
str += array[Math.round(Math.random() * (array.length - 1))];
}
return str;
}
生成RSA密鑰對
RSA密鑰對有很多種格式,因?yàn)樾枰颓岸怂惴◣旎ヂ?lián)互通,這里選擇的是1024位,Padding方式為PKSC1
public static Map<String, String> createKeysPKSC1(int keySize) {
// map裝載公鑰和私鑰
Map<String, String> keyPairMap = new HashMap<String, String>();
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
SecureRandom random = new SecureRandom();
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
generator.initialize(keySize, random);
KeyPair keyPair = generator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
String publicKeyStr = new String(Base64.encodeBase64(publicKey.getEncoded()));
String privateKeyStr = new String(Base64.encodeBase64(privateKey.getEncoded()));
keyPairMap.put("publicKey", publicKeyStr);
keyPairMap.put("privateKey", privateKeyStr);
} catch (Exception e) {
e.printStackTrace();
}
// 返回map
return keyPairMap;
}
前端DES加密
引入crypto.js第三方庫
function encryptByDES(message, key) {
var keyHex = CryptoJS.enc.Utf8.parse(key);
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
前端RSA加密
引入jsencrypt,js第三方庫
function encryptByRSA(data, publicKey) {
var encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey)
return encryptor.encrypt(data);;
}
后端RSA解密
public static String decryptPKSC1(String data, String privateKeyStr) {
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");
RSAPrivateKey privateKey = getPrivateKeyPKSC1(privateKeyStr);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
throw new RuntimeException("解密字符串[" + data + "]時(shí)遇到異常", e);
}
}
后端DES解密
public static String decrypt(String data, String key) throws IOException,
Exception {
if (data == null)
return null;
BASE64Decoder decoder = new BASE64Decoder();
byte[] buf = decoder.decodeBuffer(data);
byte[] bt = decrypt(buf, key.getBytes("UTF-8"));
return new String(bt, "UTF-8");
}
后端自定義攔截器
public class XSSFilter implements Filter, Ordered {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String contentType = request.getContentType();
if (StringUtils.isNotBlank(contentType) && contentType.contains("application/json")) {
XSSBodyRequestWrapper xssBodyRequestWrapper = new XSSBodyRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssBodyRequestWrapper, response);
} else {
chain.doFilter(request, response);
}
}
@Override
public int getOrder() {
return 9;
}
}
public class XSSBodyRequestWrapper extends HttpServletRequestWrapper {
private String body;
public XSSBodyRequestWrapper(HttpServletRequest request) {
super(request);
try{
body = XSSScriptUtil.handleString(CommonUtil.getBodyString(request));
String encrypt = request.getHeader("encrypt");
if (!StringUtil.isEmpty(encrypt)) {
String privateKey = RSAEncryptUtil.getSystemDefaultRSAPrivateKey();
String desEncryptStr = RSAEncryptUtil.decryptPKSC1(encrypt, privateKey);
JSONObject obj = JSONObject.parseObject(body);
String encryptParam = obj.getString("encryptParam");
body = DESEncryptUtil.decrypt(encryptParam, desEncryptStr);
}
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes(Charset.forName("UTF-8")));
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}到此這篇關(guān)于SpringBoot安全策略開發(fā)之集成數(shù)據(jù)傳輸加密的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)傳輸加密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring boot加入攔截器Interceptor過程解析
這篇文章主要介紹了spring boot加入攔截器Interceptor過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
Spring Security實(shí)現(xiàn)5次密碼錯誤觸發(fā)賬號自動鎖定功能
在現(xiàn)代互聯(lián)網(wǎng)應(yīng)用中,賬號安全是重中之重,然而,暴力 破解攻擊依然是最常見的安全威脅之一,攻擊者通過自動化腳本嘗試大量的用戶名和密碼組合,試圖找到漏洞進(jìn)入系統(tǒng),所以為了解決這一問題,賬號鎖定機(jī)制被廣泛應(yīng)用,本文介紹了Spring Security實(shí)現(xiàn)5次密碼錯誤觸發(fā)賬號鎖定功能2024-12-12
SpringBoot中使用@Scheduled注解創(chuàng)建定時(shí)任務(wù)的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot中使用@Scheduled注解創(chuàng)建定時(shí)任務(wù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06

