概述

JSON Web Token(JWT)和OAuth 2.0是两种不同的身份认证和授权机制,它们在互联网应用程序中都有广泛的应用。

OAuth 2.0:

  1. OAuth 2.0是一个开放标准,用于授权访问资源。它允许用户授权第三方应用程序访问他们在另一个服务提供者上的资源,而无需共享他们的凭据。OAuth 2.0定义了多种授权流程,如授权码流、密码流、客户端凭据流等。
  2. OAuth 2.0的主要角色包括资源所有者(用户)、客户端应用程序(第三方应用程序)、授权服务器(负责颁发访问令牌)和资源服务器(存储受保护资源)。
  3. OAuth 2.0的授权流程通常包括以下步骤:客户端请求授权、用户登录并授权、授权服务器颁发令牌、客户端使用令牌访问资源服务器。

JSON Web Token(JWT):

  1. JWT是一种用于安全地在两个实体之间传输信息的开放标准。它是一种紧凑且自包含的方式来表示要在实体之间传输的信息,通常用于身份验证和声明交换。
  2. JWT由三个部分组成:头部(Header)、载荷(Payload)和签名(Signature)。头部包含令牌的元数据,载荷包含实际的用户数据或声明,签名用于验证令牌的完整性和真实性。
  3. JWT通常用于认证和授权,特别是在分布式系统中,客户端在请求中携带JWT令牌,服务器端验证令牌并提取其中的信息以完成认证和授权操作。

虽然JWT和OAuth 2.0都用于认证和授权,但它们解决的问题略有不同。OAuth 2.0更专注于授权流程的定义和实现,而JWT更专注于定义一种安全、可靠的令牌格式,用于在实体之间传输信息。在实际应用中,它们经常一起使用,例如OAuth 2.0授权服务器颁发JWT令牌作为访问令牌。

JWT 示例

以下是一个简单的Java应用程序示例,演示如何使用Java JWT库创建、解析和验证JSON Web Token(JWT)

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JWTExample {

    private static final String SECRET_KEY = "mySecretKey";

    public static String createJWT(String subject, long ttlMillis) {
        // 设置JWT的签发时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        // 设置JWT的过期时间
        long expMillis = nowMillis + ttlMillis;
        Date exp = new Date(expMillis);

        // 使用HMAC SHA-256算法生成JWT
        return Jwts.builder()
                .setSubject(subject)
                .setIssuedAt(now)
                .setExpiration(exp)
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    public static Claims decodeJWT(String jwt) {
        // 解析JWT
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(jwt)
                .getBody();
    }

    public static void main(String[] args) {
        // 创建JWT
        String jwt = createJWT("user123", 3600000); // 有效期为1小时

        System.out.println("JWT Token: " + jwt);

        // 解码JWT
        Claims claims = decodeJWT(jwt);

        System.out.println("Subject: " + claims.getSubject());
        System.out.println("Issued At: " + claims.getIssuedAt());
        System.out.println("Expiration: " + claims.getExpiration());
    }
}

PS:

如果侵入者拿到jwt-token,就可以访问用户资源,这个问题的一些建议:

  1. 使用HTTPS传输:在JWT令牌的传输过程中,使用HTTPS加密来确保令牌的安全传输。

  2. 限制令牌的有效期:设置JWT令牌的有效期尽量短,并在令牌过期后需要重新进行认证。

  3. 不在JWT令牌中存储敏感信息:尽量避免将敏感信息存储在JWT令牌中,以减少泄露的影响。

  4. 使用黑名单/白名单:维护一个有效的JWT令牌的黑名单或白名单,及时取消或验证令牌的有效性。

  5. 实现令牌刷新机制:当JWT令牌即将过期时,可以使用刷新令牌机制来更新令牌,减少令牌被盗用的风险。

  6. 采用额外的安全措施:除了JWT令牌本身的安全性,还可以采用额外的安全措施,如IP限制、多因素身份验证等,来提高系统的安全性。