1.为什么要加密
由于部分数据是需要保密的比如用户名密码之类,为了防止被人抓包后数据泄露,因此需要对数据进行一定的加密,通常比较常用的就是rsa加密了.
2.工具类实现
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
/**
* rsa加密工具类
* @author sly
* @time 2018年12月12日
*/
public class RsaUtils {
public static final String KEY_ALGORITHM = "RSA";
/** 貌似默认是RSA/NONE/PKCS1Padding,未验证 */
public static final String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";
public static final String PUBLIC_KEY = "B38A579FFE8711E88737000C29048FA8";
public static final String PRIVATE_KEY = "BCB81751FE8711E88737000C29048FA8";
/** RSA密钥长度必须是64的倍数,在512~65536之间。默认是1024 */
public static final int KEY_SIZE = 2048;
/**
* 生成密钥对。注意这里是生成密钥对KeyPair,再由密钥对获取公私钥
*
* @return
*/
public static Map<String, byte[]> generateKeyBytes() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, byte[]> keyMap = new HashMap<String, byte[]>(16);
keyMap.put(PUBLIC_KEY, publicKey.getEncoded());
keyMap.put(PRIVATE_KEY, privateKey.getEncoded());
return keyMap;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* 还原公钥,X509EncodedKeySpec 用于构建公钥的规范
*
* @param keyBytes
* @return
*/
public static PublicKey restorePublicKey(byte[] keyBytes) {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
try {
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicKey = factory.generatePublic(x509EncodedKeySpec);
return publicKey;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
/**
* 还原私钥,PKCS8EncodedKeySpec 用于构建私钥的规范
*
* @param keyBytes
* @return
*/
public static PrivateKey restorePrivateKey(byte[] keyBytes) {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
try {
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateKey = factory.generatePrivate(pkcs8EncodedKeySpec);
return privateKey;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
/**
* 加密,三步走。
*
* @param key
* @param plainText
* @return
*/
public static byte[] rsaEncode(PublicKey key, byte[] plainText) {
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(plainText);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
| BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 解密,三步走。
*
* @param key
* @param encodedText
* @return
*/
public static String rsaDecode(PrivateKey key, byte[] encodedText) {
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(encodedText));
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
| BadPaddingException e) {
e.printStackTrace();
}
return null;
}
}
3.使用
以登录作为演示场景:
首先需要再跳转至登录页面时将公钥传入页面,私钥传入session
/**
*
* @param request
* @param response
* @return
* @author sly
* @time 2018年11月25日
*/
@RequestMapping("/login/toLogin")
public String toLogin(HttpServletRequest request,HttpServletResponse response) {
Map<String, byte[]> keyMap = RsaUtils.generateKeyBytes();
PublicKey publicKey = RsaUtils.restorePublicKey(keyMap.get(RsaUtils.PUBLIC_KEY));
PrivateKey privateKey = RsaUtils.restorePrivateKey(keyMap.get(RsaUtils.PRIVATE_KEY));
request.setAttribute(RsaConstant.PUBLICK_KEY, Base64.encodeBase64String(publicKey.getEncoded()));
request.getSession().setAttribute(RsaConstant.PRIVATE_KEY,privateKey);
return "/system/login/login.jsp";
}
在页面上使用js获取公钥进行加密(该js上网搜就有)
function login() {
var encrypt = new JSEncrypt();
encrypt.setPublicKey($("#publicKey").val());
// 加密后的字符串
var username = $.trim($("#username").val());
var password = $.trim($("#password").val());
var validate = $.trim($("#validate").val());
var _997D08B3 = encrypt.encrypt(username);
var _3DCBF670 = encrypt.encrypt(password);
var _1EE97457 = encrypt.encrypt(validate);
if (!username) {
layer.alert("请输入用户名!");
return;
}
if (!password) {
layer.alert("请输入密码!");
return;
}
if (!validate) {
layer.alert("请输入验证码!");
return;
}
$.ajax({
type : "post",
url : webRoot + "/system/login/login",
dataType : 'json',
data : {
a997d08b3 : _997D08B3,
a3dcbf670 : _3DCBF670,
a1ee97457 : _1EE97457,
isAjax : 1
},
success : function(data) {
if (data.status == 200) {
top.location = webRoot + "/index/home";
} else if (data.status == 300) {
eval(data.evalCode);
} else {
$("#publicKey").val(data.dataMap.publicKey);
layer.alert(data.message, { icon: 2 });
}
}
});
}
后台解密
/**
* 登录
* @param request
* @param response
* @param a997d08b3 用户名
* @param a3dcbf670 密码
* @param a1ee97457 验证码
* @return
* @author sly
* @time 2018年12月12日
*/
@ResponseBody
@RequestMapping("/login/login")
public BaseResult login(HttpServletRequest request,HttpServletResponse response,String a997d08b3,String a3dcbf670,String a1ee97457) {
try {
//获取私钥用于解密
PrivateKey privateKey = (PrivateKey) request.getSession().getAttribute(RsaConstant.PRIVATE_KEY);
//验证验证码
String validateCode = RsaUtils.rsaDecode(privateKey, Base64.decodeBase64(a1ee97457));
String verifyCode = (String) request.getSession().getAttribute(CommonConstant.LOGIN_VALIDATECODE_KEY);
if(verifyCode == null || !verifyCode.equals(validateCode)) {
return new BaseResult(ResultStatus.FAILED, Message.VERIFY_ERROR);
}
String username = RsaUtils.rsaDecode(privateKey, Base64.decodeBase64(a997d08b3));
String password = RsaUtils.rsaDecode(privateKey, Base64.decodeBase64(a3dcbf670));
BaseResult result = loginService.login(username,password);
//登录成功
if(result.getStatus() == ResultStatus.SUCCESS) {
//防止sessionId 劫持 登录成功后清除sessionId
request.getSession().invalidate();
//保存用户数据到session
request.getSession().setAttribute(CommonConstant.SESSION_USER, result.getValue(CommonConstant.SESSION_USER));
//保存登录id同步到redis用于单用户登录
String loginId = (String) result.getValue(CommonConstant.LOGIN_ID);
User existUser = FeignBeanUtils.getBaseResultObject("existUser", User.class, result);
request.getSession().setAttribute(CommonConstant.LOGIN_ID, loginId);
request.getSession().setAttribute(CommonConstant.SESSION_USER,existUser);
webRedisHelper.putValue(existUser.getUserId(),CommonConstant.LOGIN_ID);
}else {
//重新生成公钥和私钥
Map<String, byte[]> keyMap = RsaUtils.generateKeyBytes();
PublicKey publicKey2 = RsaUtils.restorePublicKey(keyMap.get(RsaUtils.PUBLIC_KEY));
PrivateKey privateKey2 = RsaUtils.restorePrivateKey(keyMap.get(RsaUtils.PRIVATE_KEY));
request.getSession().setAttribute(RsaConstant.PRIVATE_KEY,privateKey2);
//将公钥返回页面
result.setValue("publicKey", Base64.encodeBase64String(publicKey2.getEncoded()));
}
return result;
} catch (Exception e) {
logger.error(ExceptionUtils.getStackTrace(e));
return new BaseResult(ResultStatus.FAILED, LoginReturnCode.LOGIN_FAILE);
}
}
大功告成!