SpringBoot安全策略開(kāi)發(fā)之集成數(shù)據(jù)傳輸加密
前言
近期在對(duì)開(kāi)發(fā)框架安全策略方面進(jìn)行升級(jí)優(yōu)化,提供一些通用場(chǎng)景的解決方案,本文針對(duì)前后端數(shù)據(jù)傳輸加密進(jìn)行簡(jiǎn)單的分享,處理流程設(shè)計(jì)如下圖所示,本加密方法對(duì)原有項(xiàng)目兼容性較好,只需要更換封裝好的加密Ajax請(qǐng)求方法,后端統(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密鑰對(duì)
RSA密鑰對(duì)有很多種格式,因?yàn)樾枰颓岸怂惴◣?kù)互聯(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第三方庫(kù)
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第三方庫(kù)
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安全策略開(kāi)發(fā)之集成數(shù)據(jù)傳輸加密的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)傳輸加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot中Mockito單元測(cè)試入門(mén)
單元測(cè)試在很多地方都用的到,本文主要介紹了SpringBoot中Mockito單元測(cè)試入門(mén),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06java使用java.util.Date獲取指定日期的年、月、日、時(shí)、分、秒
在Java中獲取當(dāng)前時(shí)間和日期是很常見(jiàn)的操作,也是很重要的操作,下面這篇文章主要給大家介紹了關(guān)于java使用java.util.Date獲取指定日期的年、月、日、時(shí)、分、秒的相關(guān)資料,需要的朋友可以參考下2024-01-01springmvc接收參數(shù)為日期類(lèi)型詳解
這篇文章主要介紹了springmvc接收參數(shù)為日期類(lèi)型,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09Java ThreadLocal原理解析以及應(yīng)用場(chǎng)景分析案例詳解
這篇文章主要介紹了Java ThreadLocal原理解析以及應(yīng)用場(chǎng)景分析案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09springboot實(shí)現(xiàn)發(fā)送郵件(QQ郵箱為例)
這篇文章主要為大家詳細(xì)介紹了springboot實(shí)現(xiàn)發(fā)送郵件,qq郵箱代碼實(shí)現(xiàn)郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06超細(xì)講解Java調(diào)用python文件的幾種方式
有時(shí)候我們?cè)趯?xiě)java的時(shí)候需要調(diào)用python文件,下面這篇文章主要給大家介紹了關(guān)于Java調(diào)用python文件的幾種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12