RSA加密算法是一种非对称加密算法。
由后端生成公钥和私钥,公钥和私钥为一对一的关系。
将公钥传给前端,前端:公钥+value生成密文。
后端拿到密文时,取出私钥:密文 - 私钥 = value
通过这样的形式将传输内容保密。
exportKeys()可以生成公钥和私钥,为了避免运行时耗时生成秘钥,毕竟算法的东西,很吃cpu的。我的做法是先生成几对秘钥,需要时,随机获取就好了。
package com.kid.test;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import com.kid.util.RSA;
import java.io.File;
import java.util.Map;
/**
* @ClassName RSATest
* @Description TODO
* @Autor T_Antry
* @Date 2020/10/20 16:44
* @Version 1.0
*/
public class RSATest {
@Test
public void exportKeys() throws Exception {
Map<String, Object> keyMap = RSA.genKeyPair();
//公钥
String publicKey = RSA.getPublicKey(keyMap);
//私钥
String privateKey = RSA.getPrivateKey(keyMap);
System.out.println("公钥:/n" + publicKey);
System.out.println("私钥:/n" + privateKey);
}
@Test
public void testDecryptEncrypt() throws Exception {
// 公钥 可以放指定位置
String publicKeyStr = FileUtils.readFileToString(new File("/data3/pem/publickey.pem"),"UTF-8");
String privateKeyStr = FileUtils.readFileToString(new File("/data3/pem/privatekey.pem"),"UTF-8");
String sign = "abcccccc";
byte[] encryptSign = RSA.encryptByPublicKey(sign.getBytes(),publicKeyStr);
String base64Sign = Base64.encodeBase64String(encryptSign);
System.out.println("加密后的sign: "+base64Sign);
//私钥解密
byte[] decryptStr = RSA.decryptByPrivateKey(Base64.decodeBase64(base64Sign),privateKeyStr);
System.out.println("解密后的sign: "+new String(decryptStr));
}
}
public.key1=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCUbrAGx2GtC8VMD+i/4FVjZn8d3eoonKPO0f33OENe06cK/rjMNqIgul2R4NvOiRqHY6WvBlv9nKj3WoU/LTZMxcPs4tdpP57ACQw135oe9afgvDs7iC7nJLbMI01FOz1Zr1ttrBy4VEnemfZiXXWs/wEZ00Nnjv4dMNfIVeXGBQIDAQAB
private.key1=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJRusAbHYa0LxUwP6L/gVWNmfx3d6iico87R/fc4Q17Tpwr+uMw2oiC6XZHg286JGodjpa8GW/2cqPdahT8tNkzFw+zi12k/nsAJDDXfmh71p+C8OzuILucktswjTUU7PVmvW22sHLhUSd6Z9mJddaz/ARnTQ2eO/h0w18hV5cYFAgMBAAECgYBf/56VI8qGcsBtyzRLNLnFCftYw7e4AGbpUmMgyyC3acf1knzOht8gr6fouzcuQvoHamkz47cHNZUKNV9MVt9wlX7kELiAJjRb7JDgCNW5BPyujpoKmvmDbtoJ5a0d9CLDiw9s0G1x/uL/qQwEUx9WR5ZosYvA25SYGf111PQ9WQJBAN42gZbEB4I8DjJzLcYlRaxSP/m9IriMkLE+NmlBfKQrQqvN/lTF6pNMIOISyo1w3NZHIBmHRk3qes8ImwwqeI8CQQCrAFJUzkUbcflzqYQ3t4pUsOQbZ+ZQEwZHCK0dQrYKY5FbD/RJ4YilMLmlswZ6Svx/SKHZBJquU58CJIHdqxorAkBU+fcYlqJgdWLgfBdXHM3GFjYM5P0wIeD7RtU77yUhCsIWPVIzTPRlm8k/avw2lqB8+PoXiRmjljWckqfoQR2VAkEAnDRNAP7zjeCNOCSPjL3ydO6pUIeWkWrvfw/j4yi/VboiW4a1Zo/I3O0niL+CmU/KWxMkFTPpgHkOdUyX/L+BxQJAd/Z+4uyiJdsjWEUJHbrq/3UF/BBAzqsprtn/B6aZQYlSueBArTjPiLfMt8SQpp+JPAOw8F8vAw0vkT/Jt7YN1Q==
public.key2=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK2aleN1psUoT71tOn1FubyJzXz+1MQOo8xWlsKFwGfZXAZ2iIsq2B2F7UQgDMkzQOqh95J2qacIPU87uL6pCYJOnyG+VT+XldbW5y1h3zOg/dub/pZnmUM1azcvlH1m5XcGdWbEeCL2nZ2lM2152Qhwo0F2YxTX21IKK8aoAtfwIDAQAB
private.key2=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIrZqV43WmxShPvW06fUW5vInNfP7UxA6jzFaWwoXAZ9lcBnaIiyrYHYXtRCAMyTNA6qH3knappwg9Tzu4vqkJgk6fIb5VP5eV1tbnLWHfM6D925v+lmeZQzVrNy+UfWbldwZ1ZsR4IvadnaUzbXnZCHCjQXZjFNfbUgorxqgC1/AgMBAAECgYAjPD8duKBKstoqaobFpT8mFk+u+IX4ftSyXUp2dvt7bi0taVB+uBENzVGrPaCkSYrBWeyouxbzYDAkP0HNrNXKU8tU2dxHQSxxHEqLeWnxZcmCqlAsggu5q/UXOQ0wIWfBmOA6Ub4CEB4mM9qJxGs3s40CdoUS73w4mtBhgYCcwQJBAO97KiwhrXbg0X+7HFN72Pd06WDszjeHaC7f2mp1ywNkMEyT3cr5JM/FXEGEsRopF3YFJWcSSF0zvfk738FZjWECQQCUbYY0rSzKjBLtwISU/ZXyVSAI7B9Z+yZ/CrmZQzQw/AmbRylbXvYZtYqC8+b+Sk9PGpt252H295DOQvH/RcbfAkAGQJHuSwbLVr1Bd3Ia393fQAcjx6rumjNnHeMG6oJdWU1FgorE1NJYNk/dSgiRpUb+hs3eLgUDoekwy5Zg5uShAkEAklLm20ddwNAWWQxRqA/WovAIhMNCpRJTASsxjUYTTbcqQUoGG22ib/XodvC76DSZuwIgAThZ+35T4wNcTqwbQQJAKXZCBUU8oB408hMOPe80ny1YKMSDG/EvXW0L6Wuf2Xa0oBn+602wGHc+nw6gYmKXEHzxvOqDPBwCRI+Klq48Yg==
public.key3=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXD1CH6Lbw85cPp78PM/LkDrLZbjlwPkhd/9ZdzUq/3TSPykEoaElO8rN5KFp0vKl2dt+XQURAyDOvpwNfAYRQwKHRc2o4ozqPng6yTnliASU92KX0Yx6HXlmf2PimQyiLFSzyRBUv4Do/4Ef1TRH1pxFf6L5sl6u84F5Yz9HvMwIDAQAB
private.key3=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJcPUIfotvDzlw+nvw8z8uQOstluOXA+SF3/1l3NSr/dNI/KQShoSU7ys3koWnS8qXZ235dBREDIM6+nA18BhFDAodFzajijOo+eDrJOeWIBJT3YpfRjHodeWZ/Y+KZDKIsVLPJEFS/gOj/gR/VNEfWnEV/ovmyXq7zgXljP0e8zAgMBAAECgYBxDa0fijMgMa4ksU50elSWCcogoDWso3BVqVst6K7A2TS1SJFrRGFZDJr1WhYYt/m8B0tfUCFcuni0RTJosCHth2NglQlH3BYpiKQJF7twjzklfGSw5V/oATNNn2Jc7Ovr8zIQZgFEafctj8yD93TfE4zywyrcP7+B+LRxjLbCAQJBAMUyG7ppUvbyB5/lVI4JGS/YQCqsmpykYjVS05PQq/CdcG0I1WFUt+bcE4/uNU4PQxRr6HMHonHGi2l2AKi7gBMCQQDEGzKmyeFYHZPmNPcOdIALqlSgWbxDvOzTtCu/9S5lCVMynG6Zlp4UXVco7EpZ/YcP2UBtFUjHAh7XM/Nu/PhhAkBAnE9rf5D4aorHABv5Qc/n1kIH+W/bPR0UfaPnParodp1cjFVlw51R3e/m69S5U9TVvxl1fx3hi30oO8qxfmXTAkBzHFfmCVhqBaqcFXjzljTXJBtaqHHW/R2ywu5vVfbuvcOFUMenBf8yivuvfMvD+Qp/phGoNjcrAbaisc7x1jHhAkEAsHe5ZyypPoj08wp+xEQKBiU11784wOyBwZ6XWqmYOqzatEmFiHrTXKW7mQyaPQUokzxrAtDbXESzV1H4EUzjfQ==
public.key4=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuaZUCzzTqXCFnHsuoKzZRcbXgwMNo0PNScJmGpZn+o6oLa6hDnYkusn+gDEDd2QTTIUZZHyqz575kQXWM+Ttkk7yj6c/r4FnfVW1hFtgOx/UGTWMbJt+waMEF/jIiVNF/EoR4IL1X2PldmfJXJJ/9FMouP10N3MZjs6kpb+9J3QIDAQAB
private.key4=MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK5plQLPNOpcIWcey6grNlFxteDAw2jQ81JwmYalmf6jqgtrqEOdiS6yf6AMQN3ZBNMhRlkfKrPnvmRBdYz5O2STvKPpz+vgWd9VbWEW2A7H9QZNYxsm37BowQX+MiJU0X8ShHggvVfY+V2Z8lckn/0Uyi4/XQ3cxmOzqSlv70ndAgMBAAECgYEAn2GqoyuZDoVsnOB+eUor1BdWfnGI4NL5WB+/nFTeudzz+oXB+TAP+ZVynV41NMYp64of0Ddz/X1L9i//bPkgtNCyZVn1lL+2h92hWU/doLEaonLfCzwZxc0OZYFfVH7P62wdSSXR0TL02ibuF2HizN7rOf7Wa3eqxKi7VNfkx2ECQQDe40mJvJIubE+5lq6rY5+gm/d61/YN0VRwwLK+JR01Ycp/cBT+2nvxJjxpfKZDbJ9HndJLpnqxxQzXBluo761lAkEAyFK2V1wqK0cVzu6GD8LcmMbPPGjp5g91TyVr/PdlP7L15OeghfrRYwWjNthLpSEX+SQhiQ+OsS/5OIxC83W/GQJAUCkKP6E0KcIGgkaxFy7DMC4nuWSGN737UnnbTwtmD9bVzzNuOaI2RSptO7r6yPD97/HQuihrpBesYIEG4iEhCQJAQetl8W10uvUTahr3pqwa53NUsq5becdQdRD9bisC+GktnXvTSQN2b71lLiETE23Gc8e9+VpTPF9rBX6ycWcn0QJBANuSsJeG7nQGnhit3w3Q3uhdxUHCnChluOQeVS2gHJd4oGY4hapFtRLBBIQFVheJXRqAnKXXiMLZjhLGnlz8uBA=
public.key5=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDF3SXMCRMfO4rsqWnDANZ6ibW9EjmksnVA3mR2kh02BOwvZV5Y5DThPckbFiYKvOO/Q715BNRfKYwcL3TQFaYYp4PO5nDDQQzQfgLSiVOC4dUTALw3p8jtg2KcE2efarzevEQcTbOGC+2TrdxvZfl1G3teM03Kbh6dfIIdSUUNwwIDAQAB
private.key5=MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMXdJcwJEx87iuypacMA1nqJtb0SOaSydUDeZHaSHTYE7C9lXljkNOE9yRsWJgq8479DvXkE1F8pjBwvdNAVphing87mcMNBDNB+AtKJU4Lh1RMAvDenyO2DYpwTZ59qvN68RBxNs4YL7ZOt3G9l+XUbe14zTcpuHp18gh1JRQ3DAgMBAAECgYBXyKnAQDZvoOcd4Hu/vFtrujUbUT6px1MmGITR5jl3ge+Xh424OmcLl3HlxonSMcOJU/B4BKCEJ9a1mohk2XX6qaSOZcN/KNQVuytQb5vZCCJrTY+eVX8q09QpWWKVB1X+ILInTf5qzOK3Gt1/9+U51EqZ5oQej6EGfGRdVViIYQJBAPcPPhj3I2f35/lzKJu1+bnr0eiiTj8f4Ai86TpQLwiySwt5tg/U+HFifJ8TBbyrP8EPaD5IbvePgE9ZpolBJ5UCQQDNBigdOjBGOqO1VDgc6SSt0KRNtmvzyy0UGehmqzFTZjOOjmNINVLLscJzOSt9PLmebIpJI5mgDK7TZbpjjSn3AkEAjvA9sDoEPRncF6G94+D0G9JJPvvwo2rwtn19vqQ3oiNtcbU4VY6VMxyVF3/s+MxndW5RlH9Z3FclGEO5K34LxQJAMwOsKZGX/3GJ2I2rJK5yXPmEWH3ioJfWkKDdreY88MaGX5tYYtg50MtbWfZItvHMMfpJ8mb0S9m8CofOeAThAwJBAKX0siSZIOninSiKxWf8i8LNMjhHJe6o/vp5qTOneOieibv0RYbHP/HFI0NXKoQhhSeU02JI7je9N1PRO0wdSbE=
//--------------加密
var publicKey;
var ind;
var encrypt = new JSEncrypt()
getPublcKey();
function getPublcKey() {
$.ajax({
url:'./getPublicKey.do',
type:'post',
data:{
},
dataType:'json',
success:function(resp){
if(resp.success){
publicKey = resp.map.key;
ind = resp.map.index;
encrypt.setPublicKey(publicKey)
}
else
layer.msg("获取公钥失败");
}
})
}
package com.kid.handler;
import com.kid.dto.JsonMsg;
import com.kid.util.GetKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Random;
/**
* @ClassName GetPublicKeyHandler
* @Description 获取公钥
* @Autor T_Antry
* @Date 2020/10/20 21:52
* @Version 1.0
*/
@RestController
public class GetPublicKeyHandler {
@Autowired
private GetKey getKey;
@PostMapping("getPublicKey.do")
public JsonMsg getPublicKey(){
JsonMsg jm = new JsonMsg();
Random rd = new Random();
Integer index = rd.nextInt(5)+1;
String key = getKey.getPublicKey(index);
if(null==key)
{
jm.setSuccess(false);
jm.setErrorCode(999999L);
}
else
{
jm.setSuccess(true);
jm.getMap().put("key",key);
jm.getMap().put("index",index);
}
return jm;
}
}
一个封装好的,根据随机值index获取对应公钥和私钥的类,所以传公钥给前端时,把随机值一起传给前端。后面还需要这个随机的index获取私钥。
package com.kid.util;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName GetKey
* @Description 获取秘钥
* @Autor T_Antry
* @Date 2020/10/20 21:14
* @Version 1.0
*/
@Component
public class GetKey {
/**
* 公租坡手中的一串公钥
*/
private static Map<Integer,String> publicMap ;
/**
* 公租婆手中的一串私钥
*/
private static Map<Integer,String> privateMap ;
/**
* 从properties中获取公钥
*/
@Value("${public.key1}")
private String publicKey1;
@Value("${public.key2}")
private String publicKey2;
@Value("${public.key3}")
private String publicKey3;
@Value("${public.key4}")
private String publicKey4;
@Value("${public.key5}")
private String publicKey5;
/**
* 从properties中获取私钥
*/
@Value("${private.key1}")
private String privateKey1;
@Value("${private.key2}")
private String privateKey2;
@Value("${private.key3}")
private String privateKey3;
@Value("${private.key4}")
private String privateKey4;
@Value("${private.key5}")
private String privateKey5;
/**
* 通过编号获取公钥
* @param i
* @return
*/
public String getPublicKey(Integer i) {
if(publicMap==null)
{
initPublic();
}
return publicMap.get(i);
}
/**
* 通过编号获取私钥
* @param i
* @return
*/
public String getPrivateKey(Integer i) {
if(privateMap==null)
{
initPrivate();
}
return privateMap.get(i);
}
/**
* 初始化公钥
*/
private void initPublic(){
publicMap = new HashMap<>();
publicMap.put(1,publicKey1);
publicMap.put(2,publicKey2);
publicMap.put(3,publicKey3);
publicMap.put(4,publicKey4);
publicMap.put(5,publicKey5);
}
/**
* 初始化私钥
*/
private void initPrivate(){
privateMap = new HashMap<>();
privateMap.put(1,privateKey1);
privateMap.put(2,privateKey2);
privateMap.put(3,privateKey3);
privateMap.put(4,privateKey4);
privateMap.put(5,privateKey5);
}
}
没有JsonMsg,有的人可能看不懂
package com.kid.dto;
import com.kid.util.ErrorMsg;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName JsonMsg
* @Description TODO
* @Autor TT
* @Date 2020/9/7 23:48
* @Version 1.0
*/
public class JsonMsg {
/**
* 是否正确
*/
private Boolean success;
/**
* 错误代码
*/
private Long errorCode;
/**
* 错误信息
*/
private String errorMsg;
private Long id;//判断成功还是失败,1代表成功,0代表失败
private String message;//返回信息
private String location;//返回路径(如果成功了跳转到什么路径上)
private Map<String,Object> map = new HashMap<>();//如果需要分页携带什么数据下去
public JsonMsg() {
}
public JsonMsg(Long id, String message, String location, Map<String, Object> map) {
this.id = id;
this.message = message;
this.location = location;
this.map = map;
}
public JsonMsg(Boolean success, Long errorCode, String errorMsg, Long id, String message, String location, Map<String, Object> map) {
this.success = success;
this.errorCode = errorCode;
this.errorMsg = errorMsg;
this.id = id;
this.message = message;
this.location = location;
this.map = map;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public Long getErrorCode() {
return errorCode;
}
public void setErrorCode(Long errorCode) {
this.errorCode = errorCode;
errorMsg = ErrorMsg.getMsg(errorCode);//根据错误代码获取错误内容,可不要!
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}
注意要配合上面获取公钥后
var ind;
var encrypt = new JSEncrypt(); //new一个encrypt对象
var publicKey = resp.map.key;
encrypt.setPublicKey(publicKey)//且讲公钥设置到encrypt对象中
ind = resp.map.index;//存下对应的index,后端需要index找到对应的私钥
$.ajax({
url:'./login.do',
type:'post',
data:{
type:type,//登录类型随意,看需求
account:JsonData.login,//这个是账号,随意
pswd:encrypt.encrypt(JsonData.pwd),//加密
index:ind,//一定要有才
code:JsonData.code,
},
dataType:'json',
success:function(resp){
if(resp.success){
console.log('登录成功');
return;
}
}
})
/**
* 教师登录
* @param req
* @param resp
*/
@PostMapping("login.do")
private void teaLogin(HttpServletRequest req, HttpServletResponse resp,Integer index) {
String userName = req.getParameter("account");//账号
String userPswd = req.getParameter("pswd");//密码
/**
* 加密rsa
*/
try {
userPswd = new String(RSA.decryptByPrivateKey(Base64.decodeBase64(userPswd),getKey.getPrivateKey(index)));
System.err.println(userPswd);//这个可以打印看到前段传来的密码
} catch (Exception e) {
e.printStackTrace();
}
String userCode = req.getParameter("code");//验证码
String url = req.getRequestURI();
System.out.println("url:"+url);
System.out.println("教师登录");
TTeacherInfo teacherInfo = teacherInfoService.login(userName,userPswd,url);//查询登录账号是否存在
//验证验证码是否正确
//如果查询到对应账号,生成session。否则,返回错误信息
if(teacherInfo != null) {
req.getSession().setAttribute("teacher", teacherInfo);
Ajax.success(resp);//回复部分,可自定义
}else{
Ajax.error(resp,"账号密码错误");//回复部分,可自定义
}
}