1.前端所需文件
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
// 密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
'UP8iWi1Qw0Y='
// 加密
export function encrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) // 设置公钥
return encryptor.encrypt(txt) // 对数据进行加密
}
// 解密
export function decrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPrivateKey(privateKey) // 设置私钥
return encryptor.decrypt(txt) // 对数据进行解密
}
this.loginForm = {
username: username === undefined ? this.loginForm.username : username,
password: password === undefined ? this.loginForm.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
};
2.后端所用工具类
package com.nriat.site.common.utils;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* RSA加密解密
*
* @author ruoyi
**/
public class RsaUtils {
// Rsa 私钥
public static String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALRMc5+BuKvnySp5" +
"0geS+tvGSS4Kfe6/Gurfbc4GTJoUeZPnnAbdcD2NvQ9PXrpTIMW4VuXBfJ2vyE4x" +
"dM4U9PIsnHOZPqPDRqIlubnCqjuvV63THV5rvIwPsuadZvf+cnAk4HIF8g9FLNH5" +
"Exn8lRrc/ZYqOzuFkc+yuWZj57SzAgMBAAECgYAWNai0iF1AR9Ae/Fyj9DYUpotT" +
"MZWruDzPm/BBxcLf5A/J6Wjt648s9e3JGgTYPO83i+qgaMI6BnJNN4hk7m3xxg2o" +
"1mooI3e6aef3xz3H5CYwerkur22hgQpO3XXX97y0NFx/ST8lg9I1zMh63+5dHfXJ" +
"MHe5WG1+YU7gxlN1sQJBAOKgMuNoSR7Gk8ehxFWt+lM1Q0RkUhd+REVN2KsWEjaP" +
"aaxYKU5FU6p0GrStGAcvbzUaYUvXelIyk+VnVtCyvjkCQQDLqwuXtl9Iw/vsbji9" +
"o7cKUYSwmbye8Yr208qBXzebiLcY1s+PKqGyo9y/1tAxCYyyKjOv99FOC7bAHuiw" +
"+cpLAkEAotDNPqvxvHaWPVpvH886hQVDKqOYhuBkVBY1j9TviNtH5FYCdwU/srpv" +
"ZVbmaGMf1lr5g+9vJhbIQowXxyBjoQJAJSb/h15SRWDS7M8ydI2Pz0cNkHWK7eeb" +
"9OivkSgAadPnqpVM6Y3aT08K7sfN1JQsYTfHk/r96GHEpYk940K9vwJBALttsP0T" +
"l9wVKKG995ZPdxc7nSj1R9oAEPAOOGSamlFV/s7+TFBJdgOZVw4T5+GjGOY5/Rft" +
"wJvc9/lWECKRV4g=";
/**
* 私钥解密
*
* @param text 待解密的文本
* @return 解密后的文本
*/
public static String decryptByPrivateKey(String text) throws Exception {
return decryptByPrivateKey(privateKey, text);
}
/**
* 公钥解密
*
* @param publicKeyString 公钥
* @param text 待解密的信息
* @return 解密后的文本
*/
public static String decryptByPublicKey(String publicKeyString, String text) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
return new String(result);
}
/**
* 私钥加密
*
* @param privateKeyString 私钥
* @param text 待加密的信息
* @return 加密后的文本
*/
public static String encryptByPrivateKey(String privateKeyString, String text) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(text.getBytes());
return Base64.encodeBase64String(result);
}
/**
* 私钥解密
*
* @param privateKeyString 私钥
* @param text 待解密的文本
* @return 解密后的文本
*/
public static String decryptByPrivateKey(String privateKeyString, String text) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
return new String(result);
}
/**
* 公钥加密
*
* @param publicKeyString 公钥
* @param text 待加密的文本
* @return 加密后的文本
*/
public static String encryptByPublicKey(String publicKeyString, String text) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(text.getBytes());
return Base64.encodeBase64String(result);
}
/**
* 构建RSA密钥对
*
* @return 生成后的公私钥信息
*/
public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
return new RsaKeyPair(publicKeyString, privateKeyString);
}
/**
* RSA密钥对对象
*/
public static class RsaKeyPair {
private final String publicKey;
private final String privateKey;
public RsaKeyPair(String publicKey, String privateKey) {
this.publicKey = publicKey;
this.privateKey = privateKey;
}
public String getPublicKey() {
return publicKey;
}
public String getPrivateKey() {
return privateKey;
}
}
}
3.登录代码
public TokenVo login(String username, String password) {
try {
password=RsaUtils.decryptByPrivateKey(password);
}catch (Exception e) {
log.error("Failed to decrypt password: {}", e.getMessage());
throw new CustomException(ResultCodeEnum.LOGIN_DECRYPT_ERROR);
}
//封装 Authentication
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
//认证用户
Authentication authenticate;
try {
authenticate = authenticationManager.authenticate(authenticationToken);
} catch (Exception e) {
log.error("Authentication failed: {}", e.getMessage());
throw new CustomException(ResultCodeEnum.LOGIN_AUTH_ERROR);
}
//获取认证用户信息
UserDetailsInfo userDetailsInfo = (UserDetailsInfo) authenticate.getPrincipal();
boolean matches = passwordEncoder.matches(password, userDetailsInfo.getPassword());
if (!matches) {
throw new CustomException(ResultCodeEnum.LOGIN_PWD_ERROR);
}
//认证通过,生成jwt
TokenVo tokenVo=new TokenVo();
String token = jwtTokenUtil.generateToken(userDetailsInfo);
tokenVo.setToken(token);
tokenVo.setExpireTime(jwtTokenUtil.expiration);
redisCache.setCacheObject(RedisConst.REDIS_TOKEN_PREFIX+token, userDetailsInfo, jwtTokenUtil.expiration, TimeUnit.SECONDS);
return tokenVo;
}
4.灵魂一问
passwordEncoder.matches(“A”, “B”); ,如果返还是True,这个B其实就是A通过passwordEncoder.encode();加密的对吧?
不完全正确。在Spring Security中,passwordEncoder.matches(“A”, “B”)的返回值为true表示密码匹配成功,即明文密码"A"与加密后的密码"B"是匹配的。
passwordEncoder.encode(“A”)会将明文密码"A"进行加密,生成一个新的加密密码。每次调用passwordEncoder.encode(“A”)都会生成不同的加密密码,即使输入的明文密码相同。
因此,如果passwordEncoder.matches(“A”, “B”)返回true,并不意味着"B"是由"A"通过passwordEncoder.encode()加密得到的。它只表示明文密码"A"与加密密码"B"是匹配的,即密码验证成功。