• JWT工具类


    一、工具类代码

    /*
    * 总的来说,工具类中有三个方法
    * 获取JwtToken,获取JwtToken中封装的信息,判断JwtToken是否存在
    * 1. encode(),参数是=签发人,存在时间,一些其他的信息=。返回值是JwtToken对应的字符串
    * 2. decode(),参数是=JwtToken=。返回值是荷载部分的键值对
    * 3. isVerify(),参数是=JwtToken=。返回值是这个JwtToken是否存在
    * */
    public class JwtUtil {
        // 创建默认的秘钥和算法,供无参的构造方法使用
        private static final String defaultbase64EncodedSecretKey = "xxx";
        private static final SignatureAlgorithm defaultsignatureAlgorithm = SignatureAlgorithm.HS256;
    
        public JwtUtil() {
            this(defaultbase64EncodedSecretKey, defaultsignatureAlgorithm); // 调用本类的构造方法
        }
    
        private final String base64EncodedSecretKey;
        private final SignatureAlgorithm signatureAlgorithm;
    
        public JwtUtil(String secretKey, SignatureAlgorithm signatureAlgorithm) {
            this.base64EncodedSecretKey = Base64.encodeBase64String(secretKey.getBytes()); // 这样给成员变量赋值是为了让成员方法也能使用
            this.signatureAlgorithm = signatureAlgorithm;
        }
    
        /*
         * 这里就是产生jwt字符串的地方 jwt字符串包括三个部分 1. header -当前字符串的类型,一般都是“JWT”
         * -哪种算法加密,“HS256”或者其他的加密算法 所以一般都是固定的,没有什么变化 2. payload 一般有四个最常见的标准字段(下面有)
         * iat:签发时间,也就是这个jwt什么时候生成的 jti:JWT的唯一标识 iss:签发人,一般都是username或者userId exp:过期时间
         *
         */
        public String encode(String iss, long ttlMillis, Map<String, Object> claims) {
            // iss签发人,ttlMillis生存时间,claims是指还想要在jwt中存储的一些非隐私信息
            if (claims == null) {
                claims = new HashMap<>();
            }
            long nowMillis = System.currentTimeMillis();
    
            JwtBuilder builder = Jwts.builder().setClaims(claims).setId(UUID.randomUUID().toString())// 2.
                 // 这个是JWT的唯一标识,一般设置成唯一的,这个方法可以生成唯一标识
                    .setIssuedAt(new Date(nowMillis))// 1. 这个地方就是以毫秒为单位,换算当前系统时间生成的iat
                    .setSubject(iss)// 3. 签发人,也就是JWT是给谁的(逻辑上一般都是username或者userId)
                    .signWith(signatureAlgorithm, base64EncodedSecretKey);// 这个地方是生成jwt使用的算法和秘钥
            if (ttlMillis >= 0) {
                long expMillis = nowMillis + ttlMillis;
                Date exp = new Date(expMillis);// 4. 过期时间,这个也是使用毫秒生成的,使用当前时间+前面传入的持续时间生成
                builder.setExpiration(exp);
            }
            return builder.compact();
        }
    
        // 相当于encode的方向,传入jwtToken生成对应的username和password等字段。Claim就是一个map
        // 也就是拿到荷载部分所有的键值对
        public Claims decode(String jwtToken) {
    
            // 得到 DefaultJwtParser
            return Jwts.parser()
                    // 设置签名的秘钥
                    .setSigningKey(base64EncodedSecretKey) // 使用成员变量的值
                    // 设置需要解析的 jwt
                    .parseClaimsJws(jwtToken).getBody();
        }
    
        // 判断jwtToken是否合法
        public boolean isVerify(String jwtToken) {
            // 这个是官方的校验规则,这里只写了一个”校验算法“,可以自己加
            Algorithm algorithm = null;
            switch (signatureAlgorithm) {
            case HS256:
                algorithm = Algorithm.HMAC256(Base64.decodeBase64(base64EncodedSecretKey));
                break;
            default:
                throw new RuntimeException("不支持该算法");
            }
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(jwtToken); // 校验不通过会抛出异常
            // 判断合法的标准:1. 头部和荷载部分没有篡改过。2. 没有过期
            return true;
        }
    
        public static void main(String[] args) {
            JwtUtil util = new JwtUtil("tom", SignatureAlgorithm.HS256);
            // 以tom作为秘钥,以HS256加密
            Map<String, Object> map = new HashMap<>();
            map.put("username", "tom");
            map.put("password", "123456");
            map.put("age", 20);
    
            String jwtToken = util.encode("tom", 30000, map);
    
            System.out.println(jwtToken);
            util.decode(jwtToken).entrySet().forEach((entry) -> {
                System.out.println(entry.getKey() + ": " + entry.getValue());
            });
        }
    }

    如果encode的第二个参数ttlMillis为负数,表示永远不会过期。

    二、工具类的使用

    生成jwt

    @PostMapping(value = "/applogin")
        public JSONObject loginAccount(@RequestBody JSONObject json) throws Exception {
            JSONObject result = new JSONObject();
            String username = json.getString("username");
            String password = json.getString("password");
    
            // 获取用户信息
            User user = userService.getUser(username, password);
            if (user != null) {
                user.setPassword(null);    // 清除密码,即密码信息不返回给前端
                result.put("userInfo", user);
    
                // 生成token
                JwtUtil jwtUtil = new JwtUtil();
                Map<String, Object> chaim = new HashMap<>();
                chaim.put("username", username);
                String jwtToken = jwtUtil.encode(username, -1, chaim); // 参数一为签发人,第二个参数为过期时间,第三个参数为payload
                result.put("result", true);
                result.put("token", jwtToken);
            } else {
                result.put("result", false);
                result.put("msg", "用户名或密码错误");
            }
            return result;
        }

    从jwt中获取username

    public class BaseController {
    
        @Resource
        private IUserService userService;
    
        public User getSessionUser() {
            Subject subject = SecurityUtils.getSubject();
            String jwtToken = (String) subject.getPrincipal();
            JwtUtil jwtUtil = new JwtUtil();
            Claims decode = jwtUtil.decode(jwtToken);
            String phone = decode.get("username", String.class);
            QueryWrapper<User> wrapper = new QueryWrapper<User>();
            wrapper.eq("user_phone", phone).or().eq("user_no", phone);
            User user = userService.getOne(wrapper);
            return user;
        }
    }
  • 相关阅读:
    jquery 的 ajax 在 非阻塞 时返回 XMLHttpRequest
    关于TransactionScope出错:“与基础事务管理器的通信失败”的解决方法总结
    未能正确加载“radlangsvc.package,radlangsvc.vs,version=10.0.0,culture=neutra
    跨域iframe高度自适应(兼容IE/FF/OP/Chrome)
    Windows8不联网直接安装.Net 3.5 Framework的方法
    ubuntu创建、删除文件及文件夹,强制清空回收站方法
    Ubuntu java 环境变量
    mysql 和mssql2016中的json字段相关操作
    Windows任务计划
    配置mysql远程访问
  • 原文地址:https://www.cnblogs.com/zwh0910/p/15618893.html
Copyright © 2020-2023  润新知