JWT介绍和使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本文介绍了JWT的基本概念,优点和使用方法,并提供了简单的jwtToken的工具类以便快速上手使用


提示:以下是本篇文章正文内容,下面案例可供参考

一、JWT是什么?

JWT是英文JSON Web Token的缩写,看到token我们的第一印象他是认证用的。
通俗地说,JWT的本质就是一个不规则字符串,它可以将用户相关信息保存到一个Json字符串中,然后进行编码后得到一个JWT token,并且这个JWT token带有签名信息,接收后可以校验是否被篡改。

二、为什么选择JWT

1.支持跨域访问

cookie是无法跨域的,而token由于没有用到cookie(前提是将token放到请求头中),所以跨域后不会存在信息丢失问题

2.无状态

token机制在服务端不需要存储session信息,因为token自身包含了所有登录用户的信息,所以可以减轻服务端压力

3.更适用于移动端

当客户端是非浏览器平台时,cookie是不被支持的,此时采用token认证方式会简单很多

三、JWT使用

1.工具类

代码如下:

/**
 * <p>jwt token工具类</p>
 * <pre>
 *     jwt的claim里一般包含以下几种数据:
 *         1. iss -- token的发行者
 *         2. sub -- 该JWT所面向的用户
 *         3. aud -- 接收该JWT的一方
 *         4. exp -- token的失效时间
 *         5. nbf -- 在此时间段之前,不会被处理
 *         6. iat -- jwt发布时间
 *         7. jti -- jwt唯一标识,防止重复使用
 * </pre>
 */
public class JwtTokenUtil {

    /**
     * 获取用户名从token中
     */
    public static String getUsernameFromToken(String token) {
        return getClaimFromToken(token).getSubject();
    }

    /**
     * 获取jwt发布时间
     */
    public static Date getIssuedAtDateFromToken(String token) {
        return getClaimFromToken(token).getIssuedAt();
    }

    /**
     * 获取jwt失效时间
     */
    public static Date getExpirationDateFromToken(String token) {
        return getClaimFromToken(token).getExpiration();
    }

    /**
     * 获取jwt接收者
     */
    public static String getAudienceFromToken(String token) {
        return getClaimFromToken(token).getAudience();
    }

    /**
     * 获取私有的jwt claim
     */
    public static String getPrivateClaimFromToken(String token, String key) {
        return getClaimFromToken(token).get(key).toString();
    }

    /**
     * 获取jwt的payload部分
     */
    public static Claims getClaimFromToken(String token) {
        return Jwts.parser()
            .setSigningKey(JwtConstants.SECRET)
            .parseClaimsJws(token)
            .getBody();
    }

    /**
     * 解析token是否正确,不正确会报异常<br>
     */
    public static void parseToken(String token) throws JwtException {
        Jwts.parser().setSigningKey(JwtConstants.SECRET).parseClaimsJws(token).getBody();
    }

    /**
     * <pre>
     *  验证token是否失效
     *  true:过期   false:没过期
     * </pre>
     */
    public static Boolean isTokenExpired(String token) {
        try {
            Date expiration = getExpirationDateFromToken(token);
            return expiration.before(new Date());
        } catch (ExpiredJwtException expiredJwtException) {
            return true;
        }
    }

    /**
     * 生成token(通过用户名和签名时候用的随机数)
     */
    public static String generateToken(String userId) {
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, userId);
    }

    /**
     * 生成token(通过用户名和签名时候用的随机数) 可存额外字段 claims
     */
    public static String generateToken(Map<String, Object> claims, String userId) {
        return doGenerateToken(claims, userId);
    }

    /**
     * 生成token
     */
    private static String doGenerateToken(Map<String, Object> claims, String subject) {
        Date createdDate = new Date();
        Date expirationDate = new Date(createdDate.getTime() + JwtConstants.EXPIRATION * 1000);

        return Jwts.builder()
            .setClaims(claims)
            .setSubject(subject)
            .setIssuedAt(createdDate)
            .setExpiration(expirationDate)
            .signWith(SignatureAlgorithm.HS512, JwtConstants.SECRET)
            .compact();
    }

    /**
     * 获取混淆MD5签名用的随机字符串
     */
    public static String getRandomKey() {
        return getRandomString(6);
    }


    /**
     * 获取随机字符,自定义长度
     *
     * @author soofuju
     * @Date 2018/3/18 21:55
     */
    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}

2.使用

代码如下:

    public static void main(String[] args) {

        Map<String, Object> claims = new HashMap<>();

        claims.put("info", new UserTerminalAuthDO().setNickName("张三").setMobile("13811111111"));

        //生成JWTtoken
        String token = JwtTokenUtil.generateToken(claims, "1");

        //获取token存储的userId
        String usernameFromToken = JwtTokenUtil.getUsernameFromToken(token);

        //获取token存储的claims
        Claims claimFromToken = JwtTokenUtil.getClaimFromToken(token);

    }

总结

JWT的确有他自己的优势,但是任何的方法都存在它的局限性,JWT也不例外:Jwt生成之后无法修改(发生变化)、而且JWT的token长度与其包含用户信息多少正相关,传输开销较大、无法吊销令牌,只能等待令牌自身过期。所以还是需要根据具体的开发需求选择适合的方法进行开发。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值