前端vue RSA加密
一、安装
npm install jsencrypt --save-dev
二、创建js文件
在src目录下创建util文件夹,然后在util文件夹下创建 security.js 文件。
1、引入jsencrypt
//引入加密模块
import JSEncrypt from 'jsencrypt';
2、编写加密方法
export default{
//此处的加密方法可根据实际情况自定义,比如公钥可以直接写在这个js文件中,我这里是需要实时从后端返回公钥所以这么写
encrypt(publicKey, data){
var jsEncrypt = new JSEncrypt();
jsEncrypt.setPublicKey(publicKey);
var result = jsEncrypt.encrypt(data);
return result;
}
}
3、main.js 中全局引入
//引入加密模块
import securityUtil from '@/util/security.js';
//配置全局变量
Vue.prototype.$securityUtil = securityUtil;
4、完整的js文件
//引入加密模块
import JSEncrypt from 'jsencrypt';
export default{
encrypt(publicKey, data){
var jsEncrypt = new JSEncrypt();
jsEncrypt.setPublicKey(publicKey);
var result = jsEncrypt.encrypt(data);
return result;
}
}
5、在vue页面使用加密
async login() {
//获取公钥
await this.$axios.post('/user/security').then((res) =>{
let pubkey = res.data;
//加密密码
this.form.password = this.$securityUtil.encrypt(pubkey, this.form.password);
//登录
this.$axios.post("/user/login", this.form, {headers:{'Authorization':pubkey}}).then((res) => {
if (res.data.success) {
this.$message.success(res.data.message);
} else {
this.$message.error(res.data.message);
}
});
})
}
后端java RSA解密
后端解密的难点在于前端的 jsencrypt 使用的规范与java的不一样,会导致各种报错,我也在这个地方尝试了很久才找到合适的方法。
本文秘钥采用sa-token框架的SaSecureUtil.rsaGenerateKeyPair()
获取,当然也可以用其他方式获取。
因为每一次请求的公钥都不一样,所以我在前端中将公钥通过请求头返回给了后端,目的是为了匹配到对应的私钥完成解密。
前端请求头加入了Authorization
参数,所以后端需要放行这个参数。
.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, token, Accept, Authorization")
一、创建工具类:SecurityUtil
public class SecurityUtil {
/**
* 每次产生的秘钥放在这里,使用完毕后会删除,key为公钥,value为私钥
*/
public static Map<String, String> map = new HashMap<>();
/**
* 获取公钥私钥,并返回公钥
* @return
*/
public static String getPubKey(){
HashMap<String, String> keyMap = new HashMap<>();
try {
keyMap = SaSecureUtil.rsaGenerateKeyPair();
} catch (Exception e) {
e.printStackTrace();
}
String publicKey = keyMap.get("public");
String privateKey = keyMap.get("private");
map.put(publicKey, privateKey);
return publicKey;
}
/**
* 解密
* @param pubKey
* @param value
* @return
*/
public static String decrypt(String pubKey, String value){
String priKey = map.get(pubKey);
String decrypt = null;
try {
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(value.getBytes("gbk"));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(priKey);
RSAPrivateKey pri = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pri);
decrypt = new String(cipher.doFinal(inputByte));
//解密完成,删除该公钥私钥
map.remove(pubKey);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decrypt;
}
}
二、编写接口
1、编写获取公钥接口
@PostMapping("/security")
public String security(){
return SecurityUtil.getPubKey();
}
2、编写登录接口
@RequestMapping("login")
public JsonResult doLogin(@RequestBody LoginUserVo user, HttpServletRequest request) {
//获取公钥
String pubKey = request.getHeader("Authorization");
//加密
user.setPassword(SecurityUtil.decrypt(pubKey, user.getPassword()));
//登录验证
LoginUserVo u = userService.login(user);
if(u != null){
return ResultTool.success("登录成功");
}
return ResultTool.fail("登录失败");
}