深入了解JWT:Json Web Token在网络应用中的安全传递与单点登录应用

深入了解JWT:Json Web Token在网络应用中的安全传递与单点登录应用

Json web token (JWT),是一种基于 JSON 执行的开放标准((RFC 7519),用于在网络应用环境间传递声明。这种 token 设计得很紧凑且安全,特别适合分布式站点的单点登录(SSO)场景。JWT 的声明通常用于在身份提供者与服务提供者之间传递已认证的用户身份信息,这样能便于从资源服务器获取资源。同时,还可以添加一些其他业务逻辑所必需的声明信息。此 token 既可以直接用于认证,也可以进行加密。

jwt的组成

示例:

Header:
{
  "alg": "HS256",
  "typ": "JWT"
}
Claims:
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
Signature:
将 Header 进行 base64UrlEncode 编码,然后加上一个点“.”,再将 Claims 进行 base64UrlEncode 编码

加密生成的token:

请提供具体需要改写的句子呀,你只给了一个链接,没有实际的句子内容呢。

请阅读这篇文章来了解有关 JWT 的详细介绍:JWT 学习(一):什么是 JWT?- JSON WEB TOKEN

JJWT

JJWT 是一个 Java 库,能够提供端到端的 JWT 创建与验证服务。它一直是免费且开源的(遵循 Apache License,版本 2.0)。JJWT 非常易于使用和理解。该库被设计成以建筑为中心的流畅界面,将其大部分复杂性都隐藏了起来。

JJWT 规范兼容

下面我们根据 上的demo,来介绍下 JJWT 的用法。

JJWT 安装

jjwt 为我们提供了两种构建方式,分别是 Maven 和 Gradle。使用 Maven 构建时,只需进行如下配置即可使用 JJWT。

<dependency>     
	<groupId>io.jsonwebtokengroupId>     
	<artifactId>jjwtartifactId>     
	<[id_2025679897]>0.9.0version>
dependency>

Gradle 使用方式如下:

dependencies { compile io.jsonwebtoken 为 jjwt,版本号是 0.9.0 }

JJWT 是依赖于 Jackson 2.x 的。如果您的应用程序中已经使用了旧版本的 Jackson,那么就需要升级相关配置。

示例代码 签发JWT

public static String createJWT() {
SignatureAlgorithm 为签名算法。= SignatureAlgorithm.HS256;
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setId(id)                                      // JWT_ID
                .setAudience("")                                // 接受者
                .setClaims(null)                                // 自定义属性
                .setSubject("")                                 // 主题
                .setIssuer("")                                  // 签发者
                .setIssuedAt(new Date())                        // 签发时间
                .setNotBefore(new Date())                       // 失效时间
                .setExpiration(long)                                // 过期时间
                .signWith(signatureAlgorithm, secretKey);           // 签名算法以及密匙
        return builder.compact();
}

验证JWT

public static Claims parseJWT(String jwt) throws Exception {
    SecretKey secretKey = generalKey();
    return Jwts.parser()
        .setSigningKey(secretKey)
        .parseClaimsJws(jwt)
        .getBody();
}

完整示例

import com.google.gson.Gson;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtil {
    /**
     * 由字符串生成加密key
     *
     * @return
     */
    public SecretKey generalKey() {
        String stringKey = Constant.JWT_SECRET;
        // 本地的密码解码
        byte[] encodedKey = Base64.decodeBase64(stringKey);
        // 根据给定的字节数组使用AES加密算法构造一个密钥
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
    /**
     * 创建jwt
     * @param id
     * @param issuer
     * @param subject
     * @param ttlMillis
     * @return
     * @throws Exception
     */
    public String createJWT(String id, String issuer, String subject, long ttlMillis) throws Exception {
        指定签名时所使用的签名算法,也就是位于 header 那部分的内容,jjwt 已经对其进行了封装。
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        // 生成JWT的时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        创建 payload 的私有声明,这是根据特定的业务需要来添加的。如果要用这个做验证,通常需要提前与 jwt 的接收方沟通好验证方式。
        Map<String, Object> claims = new HashMap<>();
        claims.put("uid", "123456");
        claims.put("user_name", "admin");
        claims.put("nick_name", "X-rapido");
        生成签名时使用的密钥是 secret,务必牢记此密钥不能向外泄露。它是你服务端的私钥,在任何场合都不应被透露出去。
        客户端得知这个 secret 后,就意味着它可以自我签发 jwt 了。
        SecretKey key = generalKey();
        下面开始为 payload 添加各种标准声明以及私有声明。
        JwtBuilder builder = Jwts.builder() 这里实际上是创建一个 JwtBuilder ,然后对 jwt 的主体进行设置
                .setClaims(claims)          如果存在私有声明,需先设置自己创建的私有声明。此操作是给 builder 的 claim 赋值,若写在标准声明赋值之后,就会覆盖那些标准声明。
                .setId(id)                  设置 jti(JWT ID),它是 JWT 的唯一标识。依据业务需求,此标识可设置为一个不重复的值,主要用于充当一次性 token,以此来规避重放攻击。
                .setIssuedAt(now)           // iat: jwt的签发时间
                .setIssuer(issuer)          // issuer:jwt签发人
                .setSubject(subject)        这个 JWT 的主体代表它的所有人,它是一个 json 格式的字符串,可用于存放诸如 userid、roldid 之类的信息,作为用户的唯一标志。
                .signWith(signatureAlgorithm, key); // 设置签名使用的签名算法和签名使用的秘钥
        // 设置过期时间
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }
        return builder.compact();
    }
    /**
     * 解密jwt
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public Claims parseJWT(String jwt) throws Exception {
        SecretKey key = generalKey();  //签名秘钥,和生成的签名的秘钥一模一样
        Claims claims = Jwts.parser()  //得到DefaultJwtParser
                .setSigningKey(key)                 //设置签名的秘钥
                .parseClaimsJws(jwt).getBody();     //设置需要解析的jwt
        return claims;
    }
    public static void main(String[] args) {
        User user = new [id_1000257128]("tingfeng", "bulingbuling", "1056856191");
        String subject = new Gson().toJson(user);
        try {
            JwtUtil util = new JwtUtil();
            String jwt = util.createJWT(Constant.JWT_ID, "Anson", subject, Constant.JWT_TTL);
            System.out.println("JWT:" + jwt);
            System.out.println("\n解密\n");
            Claims c = util.parseJWT(jwt);
            System.out.println(c.getId());
            System.out.println(c.getIssuedAt());
            System.out.println(c.getSubject());
            System.out.println(c.getIssuer());
            System.out.println(c.get("uid", String.class));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

常量类:Constant.java

import java.util.UUID;
public class Constant {
    public static final String JWT_ID = UUID.randomUUID().toString();
    /**
     * 加密密文
     */
    public static final String JWT_SECRET = "woyebuzhidaoxiediansha";
    public static final int JWT_TTL = 60*60*1000;  //millisecond
}

输出示例:

JWT:eyJhbGciOiJIUzI1NiJ9.如果你只是希望我对这段代码进行某种形式的改写或处理,而不考虑其具体含义,那可能需要更多的具体要求和指导,例如改写为某种特定的编程语言语法、进行语法分析等。请提供更详细的信息,以便我更好地为你服务。.此句内容不完整且含义不明,无法准确进行改写。请提供完整的句子或明确其具体所指等相关信息,以便我能更好地为你提供帮助。
解密
a4d9204f-db37-4adf-8145-bdcf00331ff6
Thu Mar 29 16:02:04 CST 2018
{"nickname":"tingfeng","wechat":"bulingbuling","qq":"1056856191"}
Anson
123456

通常我们仅需将验证操作设置为中间件或拦截器。在请求后端 API 接口时,借助过滤器来获取 header 中的 token,进而验证其是否正确以及是否过期等情况。

Source Code

码云(gitee):

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

24阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

27阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

23阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

25阅读