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 安全 程序员
[JavaWeb]——JWT令牌技术,如何从获取JWT令牌
[JavaWeb]——JWT令牌技术,如何从获取JWT令牌
|
6天前
|
存储 JSON 算法
SpringBoot之JWT令牌校验
SpringBoot之JWT令牌校验
23 2
|
6天前
|
JSON 前端开发 Java
JWT解密:探秘令牌魔法与Java的完美交互
JWT解密:探秘令牌魔法与Java的完美交互
27 0
JWT解密:探秘令牌魔法与Java的完美交互
|
6天前
|
前端开发 数据安全/隐私保护
JWT令牌
JWT令牌
16 0
|
6天前
|
JSON 前端开发 Java
|
6天前
|
前端开发 Java Spring
SpringBoot通过拦截器和JWT令牌实现登录验证
该文介绍了JWT工具类、匿名访问注解、JWT验证拦截器的实现以及拦截器注册。使用`java-jwt`库生成和验证JWT,JwtUtil类包含generateToken和verifyToken方法。自定义注解`@AllowAnon`允许接口匿名访问。JwtInterceptor在Spring MVC中拦截请求,检查JWT令牌有效性。InterceptorConfig配置拦截器,注册并设定拦截与排除规则。UserController示例展示了注册、登录(允许匿名)和需要验证的用户详情接口。
258 1
|
6天前
|
JSON 前端开发 算法
掌握JWT:解密身份验证和授权的关键技术
掌握JWT:解密身份验证和授权的关键技术
|
6天前
JWT令牌的使用
JWT令牌的使用
57 0
|
6天前
|
安全 数据安全/隐私保护
Springboot+Spring security +jwt认证+动态授权
Springboot+Spring security +jwt认证+动态授权
|
6天前
|
SQL 安全 Java
微服务之Springboot整合Oauth2.0 + JWT
微服务之Springboot整合Oauth2.0 + JWT
19 1