RSA加密:web前端使用者名密碼加密以及java後端解密
編寫加解密公共方法類RSAUtils
package com.zhizhenkeji.administrative.common.utils;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
public class RSAUtil {
private static final KeyPair keyPair = initKey();
private static KeyPair initKey() {
try {
Provider provider =new BouncyCastleProvider();
Security.addProvider(provider);
SecureRandom random = new SecureRandom();
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
generator.initialize(1024,random);
return generator.generateKeyPair();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
public static String generateBase64PublicKey() {
PublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
return new String(Base64.encodeBase64(publicKey.getEncoded()));
}
public static String decryptBase64(String string) {
return new String(decrypt(Base64.decodeBase64(string.getBytes())));
}
private static byte[] decrypt(byte[] byteArray) {
try {
Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
Security.addProvider(provider);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
PrivateKey privateKey = keyPair.getPrivate();
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] plainText = cipher.doFinal(byteArray);
return plainText;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
後端生成公鑰方法
@RequestMapping(value = "/xxx", method = RequestMethod.GET)
public JsonResult RSAKey(){
String publicKey = RSAUtil.generateBase64PublicKey();
return JsonResult.getSuccessJsonResult("publicKey",publicKey);
}
前端在向背景發起登入請求之前,先請求背景擷取公鑰的方法,然後經過加密之後再發起登入請求。
form.on('submit(signin)', function (data) {
// 先擷取公鑰,然後送出使用者名和密碼給背景
$.ajax({
url: "擷取公鑰的請求路徑",
type: "GET",
dataType: "json",
async: false,
success: function (res) {
var encrypt = new JSEncrypt();//建立加密執行個體
if (res) {
// console.log(res.data);
var publicKey = null;
publicKey = res.data;//後端傳回來的公鑰
var username;
var password;
encrypt.setPublicKey(publicKey);// 初始化公鑰
username = encrypt.encrypt(data.field.username.trim());// 加密使用者名資料
password = encrypt.encrypt(data.field.password.trim());// 加密密碼資料
// console.log(username);
// console.log(password);
// 送出加密後的使用者名和密碼給背景
$.ajax({
url: "登入請求路徑",
data: {
"username": username,
"password": password
},
type: "GET",
dataType: "json",
success: function (result) {
if (result.rtnCode == "000000") {
layer.alert("登入成功!")
// window.top.location.href = './index.html';
} else {
layer.alert(result.data.rtnMsg);
}
},
error: function (e) {
layer.alert("登入失敗!");
}
});
};
}
});
});
前端代碼需引入jsencrypt.min.js檔案,這個js檔案網上一大堆,随便搜搜就有。
後端接收前端傳輸過來的密文進行解密
username = RSAUtil.decryptBase64(username.trim());
password = RSAUtil.decryptBase64(password.trim());
後端代碼需要導入的依賴jar
需要導入的依賴jar
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
注意:
Http請求特殊符号變空格的問題:參數經過Base64編碼會有’+'加号,後端request.request.getParameter(name)擷取的值中+号變成了空格。
解決辦法:request.getParameter(nms).replaceAll(" ", “+”)