前言
近期在对开发框架安全策略方面进行升级优化,提供一些通用场景的解决方案,本文针对前后端数据传输加密进行简单的分享,处理流程设计如下图所示,本加密方法对原有项目兼容性较好,只需要更换封装好的加密Ajax请求方法,后端统一拦截判断是否需要解密即可
生成DESKey
生成的DES加密密钥一定是8的整数倍的位数
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密钥对有很多种格式,因为需要和前端算法库互联互通,这里选择的是1024位,Padding方式为PKSC1
public static MapcreateKeysPKSC1(int keySize) { // map装载公钥和私钥 Map keyPairMap = new HashMap (); 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 + "]时遇到异常", 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) { } }; } }
到此这篇关于SpringBoot安全策略开发之集成数据传输加密的文章就介绍到这了,更多相关SpringBoot数据传输加密内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!