JWT学习笔记

了解 JWT Token 释义及使用 | Authing 文档

JSON Web Token Introduction - jwt.io

JSON Web Token (JWT,RFC 7519 (opens new window)),是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519)。该 token 被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该 token 也可直接被用于认证,也可被加密。

1. 认证

传统的Session认证方式需要在服务器端存储用户登录信息,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。基于Token的认证方式不需要在服务端去保留用户的认证信息或者会话信息。

流程上是这样的:

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息
  • 服务器通过验证发送给用户一个token
  • 客户端存储token,并在每次请求时附送上这个token值
  • 服务端验证token值,并返回数据

2. JWT的结构

它采用缩写的形式,包含三个部分,由.分割,包括以下三个部分

  • Header------头部
  • Payload------有效荷载
  • Signature------签名

因此JWT呈现为这种形式:

xxxxx.yyyyy.zzzzz

2.1. Header

头部包含两个部分:(1)token的类型,即JWT;(2)使用的签名算法,如HMAC、SHA256或RSA

例如:

{
  "alg": "HS256",
  "typ": "JWT"
}

2.2. Payload

该部分包含一些实体和数据的声明,如用户等,包括已注册声明、公开声明、私有声明三类。

例如:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

2.3. Signature

要创建签名部分,您必须获取编码的标头、编码的有效负载、密钥、标头中指定的算法,然后对其进行签名。

3. 使用

jjwt10:GitHub - jwtk/jjwt: Java JWT: JSON Web Token for Java and Android

目前jjwt10以上版本和jjwt9使用方法不同,好像使用jjwt9还是偏多一些。

jjwt9:jjwt 0.9.1 javadoc (io.jsonwebtoken)

以下代码是从mall项目中学习的JWT的工具类,一般可作为模板使用,主要提供了生成token和解析token的API,使用的是jjwt9

@Component
public class JwtTokenUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class);

    //sub: subject,主体,即登录的主体,一般是用户名
    private static final String CLAIM_KEY_USERNAME = "sub";

    //created表示创建时间
    private static final String CLAIM_KEY_CREATED = "created";
    @Value("${jwt.secret}")
    private String secret;
    @Value("${jwt.expiration}")
    private Long expiration;

    /**
     * 根据负载生成JWT的token
     * @param claims 声明,即JWT中的payload部分
     * @return token:String
     */
    private String generateToken(Map<String, Object> claims) {
        return Jwts.builder()   //生成一个DefaultJwtBuilder类实例
                .setClaims(claims)      //设置该DefaultJwtBuilder类实例的claims字段
                .setExpiration(generateExpirationDate())    //设置过期时间
                .signWith(SignatureAlgorithm.HS512, secret) //设置签名算法、密钥
                .compact();     //调用compact函数才能生成JWT
    }

    /**
     * 从token中获取JWT中的负载
     * @param token
     * @return Claims类实例
     */
    private Claims getClaimsFromToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            LOGGER.info("JWT格式验证失败:{}",token);
        }
        return claims;
    }

    /**
     * 根据expiration生成token的过期时间
     * @return Date
     */
    private Date generateExpirationDate() {
        return new Date(System.currentTimeMillis() + expiration * 1000);
    }

    /**
     * 从token中获取登录用户名
     */
    public String getUserNameFromToken(String token) {
        String username;
        try {
            Claims claims = getClaimsFromToken(token);
            username =  claims.getSubject();
        } catch (Exception e) {
            username = null;
        }
        return username;
    }

    /**
     * 验证token是否还有效
     *
     * @param token       客户端传入的token
     * @param userDetails 从数据库中查询出来的用户信息
     */
    public boolean validateToken(String token, UserDetails userDetails) {
        String username = getUserNameFromToken(token);
        return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }

    /**
     * 判断token是否已经失效
     */
    private boolean isTokenExpired(String token) {
        Date expiredDate = getExpiredDateFromToken(token);
        return expiredDate.before(new Date());
    }

    /**
     * 从token中获取过期时间
     */
    private Date getExpiredDateFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return claims.getExpiration();
    }

    /**
     * 根据用户信息生成token
     * @param userDetails UserDetails类实例
     * @return token
     */
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
        claims.put(CLAIM_KEY_CREATED, new Date());
        return generateToken(claims);
    }
}
相关推荐
图图图图爱睡觉5 天前
大白话解释认证JWT是什么 有什么用 怎么用
jwt
lixww.cn25 天前
ASP.NET Core对JWT的封装
asp.net core·jwt·authorize
lixww.cn25 天前
ASP.NET Core JWT Version
asp.net core·jwt·filter·identity
lixww.cn1 个月前
ASP.NET Core JWT
asp.net core·jwt
kong79069281 个月前
电商系统-用户认证(三)基于公钥解析JWT令牌
jwt·用户认证·解析jwt令牌
一只淡水鱼661 个月前
【spring】集成JWT实现登录验证
java·spring·jwt
梦幻加菲猫2 个月前
JWT在线解密/解码 - 加菲工具
jwt·jwt 在线解密/解码·jwt在线解密·jwt在线解码
脸红ฅฅ*的思春期2 个月前
JAVA安全—JWT攻防&Swagger自动化&Druid泄露
java·安全·自动化·jwt
盛夏绽放3 个月前
Node.js中JWT的token完整生命周期管理:从生成到销毁
后端·node.js·jwt