JWT令牌技术

简介: JSON Web Token (JWT) 是一种安全的、自包含的信息传输格式,常用于身份验证和信息交换。它由Header、Payload和Signature三部分组成,其中Signature用于验证消息完整性和发送者身份。JWT包含用户信息,服务器登录后发送给客户端,客户端使用JWT证明身份访问受保护资源。在Java项目中,可以使用`java-jwt`库进行JWT的生成和解析。要开始使用JWT,需在Maven或Gradle中添加相关依赖,并实现生成和解析JWT的方法。此外,文中还提供了一个简单的Java Web应用示例,展示如何在用户登录和访问受保护资源时使用JWT。

1、什么是jwt

简介

  • 全称:JSON Web Token
  • 定义了一种简介的、自包含的格式,用于在通信双方以json数据格式安全的传输信息,由于数字签名的存在,这些消息都是可靠的
  • JWTs可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。

2、JWT的使用

JWTs通常用于以下场景:

  1. 身份验证:在用户登录后,服务器会生成一个包含用户信息的JWT,并将其发送给客户端。客户端随后可以使用这个JWT来证明自己的身份,访问受保护的资源。

  2. 信息交换:JWT可以安全地在两个系统之间传输信息,因为这些信息是经过签名的,接收方可以验证发送方的身份以及信息的完整性。

JWT由三部分组成,分别是Header(头部)、Payload(负载)和Signature(签名):

  • Header:通常包含两部分信息,token的类型(即JWT)和采用的加密算法(如HS256)。
    示例:

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

    然后,这个头部会被Base64Url编码。

  • Payload:包含一些用户信息或其他需要传递的数据。这些信息会被Base64Url编码,但是即使编码后也易于解码,因此不应该包含敏感信息。
    示例:

    {
         
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }
    

    其中,sub是主题(即用户的标识),name是用户名,iat是签发时间。

  • Signature:是用于验证消息在传递过程中未被篡改的签名。它通过组合Header和Payload,然后使用密钥和相应的签名算法生成。
    示例:

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

JWT的一个重要特性是它的自包含性。由于所有必要的信息都包含在JWT自身,因此它不依赖于外部的验证。这使得JWT非常适合在不同域之间传递信息。

然而,JWT也有一些安全考虑。例如,如果JWT被泄露,由于它是自验证的,攻击者可以无限期使用它,直到它过期。因此,在使用JWT时,需要确保它的传输是安全的(例如,通过HTTPS),并且对于敏感操作,应该使用短期有效的JWT。

3、JWT简单入门

​ 在Java项目中使用JWT(JSON Web Token),你需要添加相应的依赖到你的项目构建配置文件中。根据你使用的构建工具不同,添加依赖的方式也会有所不同。以下是两种常见的构建工具Maven和Gradle的依赖添加方法:

Maven

如果你的项目使用Maven构建系统,你可以在项目的pom.xml文件中添加以下依赖:

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.14.0</version> <!-- 请使用最新的版本号 -->
</dependency>

Gradle

如果你的项目使用Gradle构建系统,你可以在build.gradle文件中添加以下依赖:

compile 'com.auth0:java-jwt:3.14.0' // 请使用最新的版本号

在添加了依赖之后,你可以通过执行Maven或Gradle的构建命令来下载并添加JWT库到你的项目中,这样你就可以开始使用JWT相关的功能了。

创建getJwt 方法

这个方法用于生成JWT。步骤如下:

  1. 创建一个 Map 来存储JWT的载荷(claims),并设置用户的ID和用户名。
  2. 使用 Jwts.builder() 创建一个新的JWT构建器。
  3. 通过 .setClaims(claims) 方法将载荷添加到JWT中。
  4. 使用 .signWith(SignatureAlgorithm.HS256, "xiaolin") 方法设置签名算法和签名密钥(在这里是 "xiaolin")。
  5. 通过 .setExpiration(new Date(System.currentTimeMillis() + 2 * 3600 * 1000)) 方法设置JWT的过期时间(这里设置为2小时后)。
  6. 使用 .compact() 方法生成JWT字符串。
  7. 打印生成的JWT字符串。
    @Test
    public void getJwt(){
   
        //设置载荷
        Map<String,Object> claims = new HashMap<>();
        claims.put("id",1);
        claims.put("username","tom");

        //生成令牌
        String token = Jwts.builder()
                .setClaims(claims)  //设置载荷
                .signWith(SignatureAlgorithm.HS256, "xiaolin")  //设置加密算法和签名
                .setExpiration(new Date(System.currentTimeMillis() + 2 * 3600 * 1000))  //设置过期时间
                .compact();

        System.out.println("令牌" + token);
    }

创建parserJwt 方法

这个方法用于解析JWT。步骤如下:

  1. 使用 Jwts.parser() 创建一个新的JWT解析器。
  2. 通过 .setSigningKey("xiaolin") 方法设置签名密钥,以便解析器可以验证签名。
  3. 使用 .parseClaimsJws(token) 方法解析JWT,并获取其载荷。
  4. 从载荷中提取ID和用户名。
  5. 打印提取的ID和用户名。
    @Test
    public void parserJwt(){
    

        //解析token
        Claims claims = Jwts.parser()
                .setSigningKey("xiaolin")  //设置签名
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNzEwOTM5MDA3LCJ1c2VybmFtZSI6InRvbSJ9.Ec5VTcB8Gj92ZzrGuZE0mAX3onkn-n9fqJjwwi2Zqss")
                .getBody();

        //获取载荷数据
        Integer id = (Integer) claims.get("id");
        String username = (String) claims.get("username");

        //打印
        System.out.println(id+":"+username);
    }

4、代码案例

为了提供一个实际的代码实现示例,我们将创建一个简单的Java Web应用程序,使用JWT进行用户身份验证和授权。这个例子将包括用户登录、生成JWT、验证JWT和使用JWT访问受保护资源的基本流程。

1. 添加JWT依赖

首先,确保你的pom.xml文件中包含了JWT的依赖:

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.14.0</version> <!-- 请使用最新的版本号 -->
</dependency>
2. 创建JWT工具类

创建一个JWT工具类,用于生成和验证JWT:

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtil {
   

    private static final String SECRET_KEY = "your-secret-key"; // 密钥应该安全存储

    public static String generateToken(Map<String, Object> claims) {
   
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时后过期
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    public static Map<String, Object> getClaims(String token) {
   
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    }
}
3. 用户登录

创建一个用户登录的端点,如果用户认证成功,返回JWT:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AuthController {
   

    public String login(HttpServletRequest request, HttpServletResponse response) throws IOException {
   
        // 这里应该有用户认证逻辑,例如检查用户名和密码
        // 假设认证成功
        Map<String, Object> claims = new HashMap<>();
        claims.put("username", "user");
        claims.put("role", "admin");

        String token = JwtUtil.generateToken(claims);

        // 设置HTTP响应头,以便现代浏览器不会缓存响应
        response.setHeader("Cache-Control", "no-store");
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", 0);

        return token;
    }
}
4. 受保护的资源

创建一个受保护资源的端点,只有带有有效JWT的请求才能访问:

public class ProtectedResourceController {
   

    public String getResource(HttpServletRequest request) {
   
        String token = request.getHeader("Authorization").substring("Bearer ".length()); // 从HTTP请求头获取JWT
        Map<String, Object> claims = JwtUtil.getClaims(token);

        // 根据claims中的信息进行权限验证
        // 假设验证成功
        if ("admin".equals((String) claims.get("role"))) {
   
            return "Welcome admin!";
        } else {
   
            return "Access denied!";
        }
    }
}
5. 启动服务器

最后,你需要一个服务器来运行你的应用程序。如果你使用Spring Boot,你可以创建一个带有@SpringBootApplication注解的主类,并使用SpringBootApplication.run()方法来启动服务器。

请注意,这个例子是一个非常简化的版本,仅用于演示JWT的基本用法。在实际的生产环境中,你需要考虑更多的安全措施,例如使用HTTPS、防止CSRF攻击、密钥的安全管理等。此外,用户认证逻辑应该与数据库或其他用户存储系统集成,以验证用户的凭据。

相关文章
|
6月前
|
存储 JSON 安全
JWT令牌详解
JWT令牌详解
187 3
|
3月前
|
存储 中间件 API
ThinkPHP 集成 jwt 技术 token 验证
本文介绍了在ThinkPHP框架中集成JWT技术进行token验证的流程,包括安装JWT扩展、创建Token服务类、编写中间件进行Token校验、配置路由中间件以及测试Token验证的步骤和代码示例。
ThinkPHP 集成 jwt 技术 token 验证
|
2月前
|
存储 JSON 算法
JWT令牌基础教程 全方位带你剖析JWT令牌,在Springboot中使用JWT技术体系,完成拦截器的实现 Interceptor (后附源码)
文章介绍了JWT令牌的基础教程,包括其应用场景、组成部分、生成和校验方法,并在Springboot中使用JWT技术体系完成拦截器的实现。
126 0
JWT令牌基础教程 全方位带你剖析JWT令牌,在Springboot中使用JWT技术体系,完成拦截器的实现 Interceptor (后附源码)
|
4月前
|
JSON Java API
【Azure Developer】如何验证 Azure AD的JWT Token (JSON Web 令牌)?
【Azure Developer】如何验证 Azure AD的JWT Token (JSON Web 令牌)?
105 0
|
5月前
|
存储 JSON 安全
OAuth2与JWT在API安全中的角色:技术深度解析
【7月更文挑战第20天】OAuth2和JWT作为两种重要的安全协议,在API安全中发挥着不可或缺的作用。OAuth2通过提供灵活的授权框架,实现了对资源的细粒度访问控制;而JWT则通过其紧凑性和自包含性,确保了身份验证和信息传输的安全性。在实际应用中,将OAuth2和JWT结合使用,可以构建出既强大又安全的API服务,为用户提供更加安全、可靠和便捷的数字体验。
|
4月前
|
安全 Nacos 数据安全/隐私保护
【技术干货】破解Nacos安全隐患:连接用户名与密码明文传输!掌握HTTPS、JWT与OAuth2.0加密秘籍,打造坚不可摧的微服务注册与配置中心!从原理到实践,全方位解析如何构建安全防护体系,让您从此告别数据泄露风险!
【8月更文挑战第15天】Nacos是一款广受好评的微服务注册与配置中心,但其连接用户名和密码的明文传输成为安全隐患。本文探讨加密策略提升安全性。首先介绍明文传输风险,随后对比三种加密方案:HTTPS简化数据保护;JWT令牌减少凭证传输,适配分布式环境;OAuth2.0增强安全,支持多授权模式。每种方案各有千秋,开发者需根据具体需求选择最佳实践,确保服务安全稳定运行。
409 0
JWT令牌,JWT令牌的后续使用,在其他端口中使用的注意事项?如果你编写了JWT令牌的话,在下一次请求当中,都需要添加的,如果你已经配置好了WebConfig和Inter 就不用配了,添加了拦截器之后
JWT令牌,JWT令牌的后续使用,在其他端口中使用的注意事项?如果你编写了JWT令牌的话,在下一次请求当中,都需要添加的,如果你已经配置好了WebConfig和Inter 就不用配了,添加了拦截器之后
|
7月前
|
存储 Java 应用服务中间件
4.基础技术&API网关&JWT
4.基础技术&API网关&JWT
54 1
|
6月前
|
JSON 前端开发 数据格式
关于JWT令牌和过滤器以及拦截器的实现流程
JWT令牌用于验证用户请求合法性,登录时通过Filter或Interceptor校验账号密码,生成JWT并返回给前端保存。请求时,后端通过解析令牌检查其完整性、时效性和合法性。Filter在请求处理前检查是否携带JWT,Interceptor的preHandle方法同样用于此目的。两者选择其一即可,拦截器配置更精确但稍复杂。
|
7月前
|
存储 JSON 算法
SpringBoot之JWT令牌校验
SpringBoot之JWT令牌校验