概念
Http协议报文明文传输,如果被恶意分子抓包,未经加密的数据便一览无余。
为了数据的安全传输,可以采用对称加密和非对称加密算法保驾护航。
过程
以客户端到服务器为例。
在客户端向服务器发送数据之前,服务器将自己通过RSA算法产生的公钥交给客户端。在发送数据时,客户端用得到的公钥加密要传输的数据,加密完成后传输密文给服务器,服务器收到数据后首先使用之前产生的私钥进行解密,解密成功后得到数据。
这个过程服务器的私钥从未传输,所以恶意分子无法通过窃听获得原始的数据。
具体实现
以Spring + Thyme Leaf + Vue.js + axios为例。
产生秘钥
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Component @Scope("singleton") public class CipherUtil { private final PublicKey publicKey; private final Cipher decryptCipher;
public CipherUtil() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(1024); KeyPair keyPair = keyPairGenerator.generateKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); this.publicKey = keyPair.getPublic(); this.decryptCipher = Cipher.getInstance("RSA"); decryptCipher.init(Cipher.DECRYPT_MODE, privateKey); }
public String getPublicKey() { return Base64.getEncoder().encodeToString(publicKey.getEncoded()); }
public String decrypt(String content) throws BadPaddingException, IllegalBlockSizeException { return new String(decryptCipher.doFinal(Base64.getDecoder().decode(content))); } }
|
将服务器端产生的秘钥交给客户端
Controller
1 2 3 4 5
| @GetMapping("/") public String home(Model model) { model.addAttribute("publicKey", cipherUtil.getPublicKey()); return "home"; }
|
HTML
1 2 3
| <script th:inline="javascript"> const publicKey = [[${publicKey}]]; </script>
|
客户端使用公钥加密
拦截表单提交
1 2 3
| <form method="post" name="form" action="/submit" v-on:submit.prevent="upload"> ............. <form>
|
对数据加密后提交表单
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
| new Vue({ el: '#app', data: { xx: '', yy: '' }, methods: { upload() { const encryptor = new JSEncrypt(); encryptor.setPublicKey(publicKey);
const formData = new FormData(); formData.append("xx", encryptor.encrypt(this.xx)); formData.append("yy", encryptor.encrypt(this.yy)); formData.append("zz", this.action); axios({ method: "post", url: "/submit", headers: { "Content-Type": "multipart/form-data" }, data: formData }).then((res) => { console.log(res); }); } } });
|
服务端收到数据后解密
1 2 3 4 5 6 7 8
| @PostMapping("/submit") @ResponseBody public String submit(@RequestParam("action") String value, @RequestParam("id") String id, @RequestParam("password") String password) { id = cipherUtil.decrypt(id); password = cipherUtil.decrypt(password); return "hhh"; }
|