一、前言
最近安全测试的总是测出安全漏洞来,让开发改。
想了想干脆把请求参数都加密下,前端加密后端解密,这样总差不多了。
看了下AES加密,是对称的,前后端用这个不太行。
于是想到用RSA加密,是非对称的,可以前端加密后端解密。
二、前端代码与用法
1.前端是vue项目,使用时,需要先执行:
1 | npm i jsencrypt |
把这个依赖下载到node_modules里面。
2.可以增加一个工具类文件:项目名/src/utils/commonUtil.js,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import JSEncrypt from "jsencrypt" ; export default { encodeRSA(word, keyStr) { //这个是公钥,有入参时用入参,没有入参用默认公钥 keyStr = keyStr ? keyStr : 'MIGxxxxxxxxxxxxxxxxxxxxxxxxxx' ; //创建对象 const jsRsa = new JSEncrypt(); //设置公钥 jsRsa.setPublicKey(keyStr); //返回加密后结果 return jsRsa.encrypt(word); } } |
3.然后,需要使用的地方,就可以这样用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //引入第2步的工具类 import commonUtil from '@utils/commonUtil' //引入一个发请求的方法,这个也需要npm i import axios from 'axios' //一个发请求用的方法 export function myget(userId) { return axios.get(`/xxx/user`, { headers: { //先把参数rsa加密下,再用urlEncoder转下码,然后放header里传给后台 userId: encodeURIComponent(commonUtil.encodeRSA(userId, null )), }, }).then(res => { return res.data }) } |
这样,就把加密参数放入header里的userId里了,后台可以取出后解密。
三、后端代码与用法
1.可以先写个工具类,如下:(RSA公钥和私钥可以用这个工具类生成,然后自己记录后使用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import javax.crypto.Cipher; import java.security.KeyFactory; import java.security.Security; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Map; import java.util.HashMap; import java.security.KeyPairGenerator; import java.security.SecureRandom; import java.security.KeyPair; public class RSAUtil { //公钥,可以写前端 public static String public_key= "MIGxxxxxx" ; //私钥,只能放后端 public static String private_key= "MIICxxxxxxxx" ; public static void main(String[] args) { //解密数据 try { //生成公钥和私钥 genKeyPair(); String publicKey = keyMap.get( 0 ); //打印出来自己记录下 System.out.println( "公钥:" + publicKey); String privateKey = keyMap.get( 1 ); //打印出来自己记录下 System.out.println( "私钥:" + privateKey); //获取到后,可以放这里,测试下能不能正确加解密 publicKey = public_key; privateKey = private_key; String orgData = "test" ; System.out.println( "原数据:" + orgData); //加密 String encryptStr =encrypt(orgData,publicKey); System.out.println( "加密结果:" + encryptStr); //解密 String decryptStr = decrypt(encryptStr,privateKey); System.out.println( "解密结果:" + decryptStr); } catch (Exception e) { e.printStackTrace(); } } /** * RSA公钥加密 * * @param str 加密字符串 * @param publicKey 公钥 * @return 密文 * @throws Exception 加密过程中的异常信息 */ public static String encrypt(String str,String publicKey) throws Exception { //base64编码的公钥 byte [] decoded = decryptBASE64(publicKey); Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider()); RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec(decoded)); //RSA加密 Cipher cipher = Cipher.getInstance( "RSA" ); cipher.init(Cipher.ENCRYPT_MODE, pubKey); String outStr = encryptBASE64(cipher.doFinal(str.getBytes( "UTF-8" ))); return outStr; } /** * RSA私钥解密 * * @param str 加密字符串 * @param privateKey 私钥 * @return 明文 * @throws Exception 解密过程中的异常信息 */ public static String decrypt(String str, String privateKey) throws Exception { //64位解码加密后的字符串 byte [] inputByte = decryptBASE64(str); //base64编码的私钥 byte [] decoded = decryptBASE64(privateKey); Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider()); RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance( "RSA" ).generatePrivate( new PKCS8EncodedKeySpec(decoded)); //RSA解密 Cipher cipher = Cipher.getInstance( "RSA" ); cipher.init(Cipher.DECRYPT_MODE, priKey); String outStr = new String(cipher.doFinal(inputByte)); return outStr; } //编码返回字符串 public static String encryptBASE64( byte [] key) throws Exception { return ( new BASE64Encoder()).encodeBuffer(key); } //解码返回byte public static byte [] decryptBASE64(String key) throws Exception { return ( new BASE64Decoder()).decodeBuffer(key); } /** * 密钥长度 于原文长度对应 以及越长速度越慢 */ private final static int KEY_SIZE = 1024 ; /** * 用于封装随机产生的公钥与私钥 */ private static Map keyMap = new HashMap(); /** * 随机生成密钥对 * @throws Exception */ public static void genKeyPair() throws Exception { // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance( "RSA" ); // 初始化密钥对生成器 keyPairGen.initialize(KEY_SIZE, new SecureRandom()); // 生成一个密钥对,保存在keyPair中 KeyPair keyPair = keyPairGen.generateKeyPair(); // 得到私钥 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到公钥 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); String publicKeyString = encryptBASE64(publicKey.getEncoded()); // 得到私钥字符串 String privateKeyString = encryptBASE64(privateKey.getEncoded()); // 将公钥和私钥保存到Map //0表示公钥 keyMap.put( 0 , publicKeyString); //1表示私钥 keyMap.put( 1 , privateKeyString); } } |
2.使用时,把公钥内容放入前端js,私钥内容就放后端代码里,就可以和前端联调测试了。样例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //测试接口 @GetMapping ( "/xxx/user" ) public String myget(HttpServletRequest request) { //先用非对称算法RSA解密一下 try { //从header里获取到参数 String userId = request.getHeader( "userId" ); log.debug( "收到userId,内容为:" +userId); //这里解密,注意先用URLDecode处理了下,如果前端没有用的话,这里也不用处理 userId = RSAUtil.decrypt(URLDecoder.decode(userId, "UTF-8" ), RSAUtil.private_key); log.debug( "RSA解密成功,userId为" +userId); } catch (Exception e) { log.error( "RSA解密失败" ,e); //如果解密失败,就返回null return null ; } return "成功" ; } |
到此这篇关于vue前端RSA加密java后端解密的方法实现的文章就介绍到这了,更多相关vue RSA加密java后端解密内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!