技术栈
前端:VUE + Element-Ui
后端:SpringBoot
流程
公匙加密、私匙解密
前端流程
- 调用接口获取
rsa
公匙 - 登录时携带
rsa
公匙 和JSEncrypt
加密后的rsa密码 - 登录验证失败重新获取公匙
- 登录成功时 后端会返回
token
,在以后的请求中 请求头携带该token进行访问
后端流程
- 编写返回公匙的接口,返回前
存入redis key:公匙 value:私匙
- 登录接口中
根据公匙从redis获取私匙进行解密
密码 - 密码等校验通过后,生成token、存入redis 返回给前端
- 后端配置过滤器,过滤其它接口请求,验证
token
的有效性
前后端 rsa 加密与解密
前端加密
-
安装插件
jsencrypt
npm install jsencrypt
-
登录页面引入
import {JSEncrypt} from 'jsencrypt'
-
加密
// 新建JSEncrypt对象 let encrypt = new JSEncrypt() // 公钥加密 encrypt.setPublicKey(loginParams.rsaPublicKey) let passwordEncrpt = encrypt.encrypt(values.password)
后端对应功能
1. 导入 hutool 工具包
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.8</version>
</dependency>
2. 返回公匙
@ApiOperation("获取RSA公钥")
@GetMapping("/getRSAPublicKey")
public Result<String> getRSAPublicKey() {
RSA rsa = new RSA();
// 私匙
String privateKeyBase64 = rsa.getPrivateKeyBase64();
// 公匙
String publicKeyBase64 = rsa.getPublicKeyBase64();
//存到redis key为公钥 value为私钥
redisUtil.set(publicKeyBase64, privateKeyBase64, 300L);
return Result.message(publicKeyBase64);
}
3. 解密
- JWT工具类
public class JWTUtils { /** * 生成token,一小时后过期 * @param username 用户名 * @param secret 秘钥 * @return */ public static String sign(String username,String secret) { // 创建 token String token = JWT.create() // 数据(也就是 payload 负载) .withClaim("username", username) //过期时间 1小时 .withExpiresAt(DateUtil.offsetHour(new Date(),1)) // 设置秘钥 .sign(Algorithm.HMAC256(secret)); return token; } /** * 解密token * @param token * @throws Exception * @return */ public static DecodedJWT decoded(String token){ DecodedJWT decode = null; try { decode = JWT.decode(token); }catch (JWTDecodeException e){ return null; } return decode; } /** * 根据request中的token获取用户账号 * * @param request * @return */ public static String getUserNameByToken(HttpServletRequest request) throws Exception { String accessToken = request.getHeader("X-Access-Token"); String username = getUserNameByToken(accessToken); if (!StringUtils.hasLength(username)) { throw new Exception("未获取到用户"); } return username; } /** * 获得token中的信息无需secret解密也能获得 * * @return token中包含的用户名 */ public static String getUserNameByToken(String token) { try { DecodedJWT jwt = JWT.decode(token); return jwt.getClaim("username").asString(); } catch (JWTDecodeException e) { return null; } } /** * 校验token是否正确 * * @param token 密钥 * @param secret 用户的密码 * @return 是否正确 */ public static boolean verify(String token, String username, String secret) { try { // 根据密码生成JWT效验器 DecodedJWT jwt = JWT.require(Algorithm.HMAC256(secret)) .withClaim("username", username) .build() .verify(token); // 效验TOKEN return true; } catch (Exception exception) { return false; } } }
- 生成公匙
@GetMapping("/getPublicKey")
public String getPublicKey(){
RSA rsa = new RSA();
redisUtil.set(rsa.getPublicKeyBase64(),rsa.getPrivateKeyBase64(),300L);
return rsa.getPublicKeyBase64();
}
- 解密与获取token
// 根据公匙 从redis中获取 私匙 String rsaPrivateKey = String.valueOf(redisUtil.get(rsaPublicKey)); RSA rsa = new RSA(rsaPrivateKey, rsaPublicKey); // 解密 byte[] decrypt = rsa.decrypt(str, KeyType.PrivateKey); String password = new String(decrypt); // 生成token String token = JWTUtils.sign(username, "签名"); // 将token存入redis redisUtil.set("user_"+username,token);