JWT使用和讲解(保姆级)

JWT使用和讲解(保姆级)

JWT

jwt的定义

JWT(JSON Web Token)是一种用于在网络上传递信息的开放标准(RFC 7519)。它是一种轻量级,自包含的令牌,常被用于在客户端和服务器之间传递身份信息。JWT可以通过数字签名验证,确保信息的完整性,并且由于其简洁性,易于在URL、HTTP头部以及HTTP请求参数中传递。

结构

JWT由三部分组成:

  • Header(头部)
  • Payload(载荷)
  • Signature(签名)

这三部分使用点(.)进行分隔,形成一个紧凑的字符串。

  1. Header(头部):包含令牌的源数据,签名算法(HMAC SHA256或RSA等)和令牌类型(JWT)。

    示例:

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

    这段json数据将由Base64进行加密。

    Jwts.builder()
    	.setHeader()		//一种是Header接口的实现,一种是Map
    	.setHeaderParam() 	//向Header追加参数
    	.setHeaderParams()	//向Header追加参数
    
  2. Payload(载荷):包含需要传递的信息,分为注册声明(registered claims)、公共声明(public claims)和私有声明(private claims)。注册声明包含了一些预定义的字段,如iss(签发者)、exp(过期时间)、sub(主题)等。公共声明包含了一些标准的字段,而私有声明则是用户自定义的字段。最终也会由Base64加密

    示例:

    {
      "sub": "1234567890",	// 注册声明
      "name": "John Doe",	// 公共声明
      "admin": true			// 私有声明
    }
    

    registered claims(注册声明)

    这些是一组预定义的声明,它们并非强制性,而是推荐的,以提供一组有用的、可互操作的声明 。

    ​ 例子

    标准声明的字段有:
    iss (issuer)		该声明的内容是JWT的签发者,标识谁签发了这个令牌。
    sub (subject)		该声明的内容是JWT所面向的用户,标识该JWT所代表的主题。
    aud (audience)		该声明的内容是JWT的受众,表示这个JWT预期的接收对象。
    exp (expiration time)该声明的内容是JWT的过期时间,标识JWT令牌的有效期限。
    nbf (not before)	该声明的内容是JWT的生效时间,表示在此时间之前JWT无效。
    iat (issued at)		该声明的内容是JWT的签发时间,标识JWT的生成时间。
    jti (JWT ID)		该声明的内容是JWT的唯一标识符,用于区分其他令牌。
    
    Jwts.builder()
    	.setIssuer()	//jwt签发者
    	.setSubject()	//jwt所面向的用户
        .setAudience()	//接收jwt的一方
        .setExpiration()//jwt的过期时间,这个过期时间必须要大于签发时间
        .setNotBefore()	//定义在什么时间之前,该jwt都是不可用的
        .setIssuedAt()	//jwt的签发时间
       	.setId()		//jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
    

    public claims(公共声明)

    公共声明,名称可以被任意定义。为了防止重复,任何新的Claim名称都应该被定义在IANA JSON Web Token Registry中或者使用一个包含不易重复命名空间的URI。

    private claims(私有声明)

    私有声明,是在团队中约定使用的自定义Claims,既不属于Registered也不属于Public。

    Jwts.builder()
    	.setClaims()	//用于设置 JWT 的声明(Claims)部分,设置自定义的声明信息到 JWT 中。
    

    注意:对于已签名的Token,这些信息虽然受到保护,不会被篡改,但任何人都可以阅读。除非加密,否则不要将机密信息放在 JWT 的有效负载或头元素中

  3. Signature(签名):通过将头部载荷secret使用指定的算法进行加密生成的签名。签名用于验证消息的完整性,确保它没有被篡改。其中secret是存储在服务器端,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和验证,请勿泄露。

    示例:

    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret
    )
    

JWT的使用

创建一个新项目,引入jwt包

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

JWT工具类:

public class JwtUtil {

    // 令牌秘钥
    private static final String secret = "secret";

    // 令牌有效期(默认60分钟)
    private static final Long expiration = 60 * 60L;

    /**
     * 随机码
     */
    public static String getUUID(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }

    /**
     * 生成token
     * @param
     * @return
     */
    private static String getJwtBuilder(String subject) {
        SecretKey secretKey = generalKey();
        return Jwts.builder()									//这里其实就是new一个JwtBuilder,设置jwt的body
                .setSubject(subject)							//sub(Subject):代表这个JWT的主体,即它的所有人,是一个json字符串
                .setId(getUUID())								//设置jti(JWT ID):是JWT的唯一标识,根据业务需要
                .signWith(SignatureAlgorithm.HS256, secretKey)	//设置签名使用的签名算法和签名使用的秘钥
                .setExpiration(getExpirationDate())				//设置过期时间
                .compressWith(CompressionCodecs.GZIP)			//用于在创建 JWT 时启用 Gzip 压缩。这可以帮助减小
                												  JWT 字符串的大小,从而在传输过程中减少网络开销。
                .compact();
    }

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

    /**
     * 解析
     * @param token
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String token) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(token)
                .getBody();
    }
    
    /**
     * 生成加密后的秘钥 secretKey
     *
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getDecoder().decode(secret);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    /**
     * 获取当前token的用户信息
     * @param token
     * @return
     */
    public String getUsernameFromToken(String token){
        String username;
        try {
            Claims claims = parseJWT(token);
            username = claims.getSubject();
        }catch (Exception e){
            username = "";
        }
        return username;
    }

    /**
     * 根据用户信息生成token
     */
    public static String generateToken(User user) {
        return getJwtBuilder(JSON.toJSONString(user));
    }

    /**
     * 刷新token
     */
    public String refreshToken(String token) throws Exception {
        SecretKey secretKey = generalKey();
        String subject = Jwts
                .parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(token)
                .getBody().getSubject();

        // 验证用户信息
        User user = JSONObject.parseObject(subject,User.class);
        if (StringUtils.isEmpty(user)){
            return "";
        }
        return getJwtBuilder(JSON.toJSONString(user));
    }

}

在这里插入图片描述

在这里插入图片描述

下列是token

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJwYXNzd29yZFwiOlwiMTIzNDU2XCIsXCJ1c2VySWRcIjoxLFwidXNlcm5hbWVcIjpcImFkbWluXCJ9IiwiZXhwIjoxNzA0NDU0NTE0fQ.vSUc6NhZPHrH2mVz_6MdrvDHnAesuPZlQbOviF_atv4

img-vpdya7NQ-1704452110368)]

下列是token

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJwYXNzd29yZFwiOlwiMTIzNDU2XCIsXCJ1c2VySWRcIjoxLFwidXNlcm5hbWVcIjpcImFkbWluXCJ9IiwiZXhwIjoxNzA0NDU0NTE0fQ.vSUc6NhZPHrH2mVz_6MdrvDHnAesuPZlQbOviF_atv4

最后,在真实的项目中,一般是存放在请求头的Authorization,并加上Bearer标注最后是JWT(格式:Authorization: Bearer <token>)

  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django Rest Framework(DRF)是一种基于 Django 的 Web 应用程序开发框架,它提供了许多工具和库,使得开发 Web API 更加容易。JWT 是一种基于 JSON 的 Web Token,它用于在网络应用程序和服务器之间传递声明以使身份验证和授权更加安全。在 DRF 中使用 JWT 可以使得 API 更加安全。 JWT 由三个部分组成:头部、载荷和签名。头部通常包含算法和令牌类型的信息,载荷通常包含用户标识信息和令牌的过期时间,签名则是根据头部、载荷和密钥生成的。 DRF 支持 JWT 验证,可以使用第三方库 djangorestframework-jwt 来实现。实现方式如下: 1. 安装 djangorestframework-jwt ``` pip install djangorestframework-jwt ``` 2. 添加 JWT 相关配置到 settings.py 中 ``` REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ], } JWT_AUTH = { 'JWT_SECRET_KEY': SECRET_KEY, 'JWT_ALGORITHM': 'HS256', 'JWT_VERIFY_EXPIRATION': True, 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7), 'JWT_ALLOW_REFRESH': True, 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=30), } ``` 3. 在 urls.py 中添加 JWT 相关路由 ``` from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token urlpatterns = [ url(r'^api-token-auth/', obtain_jwt_token), url(r'^api-token-refresh/', refresh_jwt_token), url(r'^api-token-verify/', verify_jwt_token), ] ``` 4. 在需要验证的视图中添加 @jwt_authentication_classes 装饰器 ``` from rest_framework.decorators import api_view, permission_classes, jwt_authentication_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response @api_view(['GET']) @permission_classes([IsAuthenticated]) @jwt_authentication_classes def my_view(request): content = {'message': 'Hello, World!'} return Response(content) ``` 以上是 DRF 中使用 JWT 的简单介绍,JWT 的原理是将用户标识信息和过期时间等信息进行编码,生成一个安全的 token,并将其传递给客户端。客户端在后续的请求中携带这个 token,在服务端进行验证。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值