技术栈

前端:VUE + Element-Ui
后端:SpringBoot

流程

公匙加密、私匙解密

前端流程

  1. 调用接口获取rsa公匙
  2. 登录时携带rsa公匙 和 JSEncrypt加密后的rsa密码
  3. 登录验证失败重新获取公匙
  4. 登录成功时 后端会返回token,在以后的请求中 请求头携带该token进行访问

后端流程

  1. 编写返回公匙的接口,返回前 存入redis key:公匙 value:私匙
  2. 登录接口中根据公匙从redis获取私匙进行解密 密码
  3. 密码等校验通过后,生成token、存入redis 返回给前端
  4. 后端配置过滤器,过滤其它接口请求,验证token的有效性

前后端 rsa 加密与解密

前端加密

  1. 安装插件jsencrypt

    npm install jsencrypt
    
  2. 登录页面引入

    import {JSEncrypt} from 'jsencrypt'
    
  3. 加密

    	// 新建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. 解密

  1. 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;
            }
        }
        
    }
    
    
  2. 生成公匙
    @GetMapping("/getPublicKey")
    public String getPublicKey(){
        RSA rsa = new RSA();
        redisUtil.set(rsa.getPublicKeyBase64(),rsa.getPrivateKeyBase64(),300L);
        return rsa.getPublicKeyBase64();
    }
  1. 解密与获取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);
    
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐