java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java JWT实现Token认证

Java如何使用JWT实现Token认证机制

作者:pan_junbiao

JWT(JSON Web Token)是一种用于在网络上安全地传输信息的简洁的、URL 安全的表示方法,本文主要介绍了Java如何使用JWT实现Token认证机制,需要的可以参考下

1、JWT 的简述

JWT(JSON Web Token)是一种用于在网络上安全地传输信息的简洁的、URL 安全的表示方法,它定义了一个紧凑且自包含的方式,用于不同实体之间安全地传输信息(JSON格式)。以下是关于 JWT 的详细介绍:

1.1 JWT 的组成

JWT 通常由三部分组成,分别是 Header(头部)、Payload(有效载荷)和 Signature(签名)。

Header(头部):头部通常包含两部分信息,即声明类型和声明所使用的算法。声明类型通常是 JWT,而声明所使用的算法则可以是 HMACSHA256、RSA 等。头部信息会进行 Base64URL 编码,形成 JWT 的第一部分。

Payload(有效载荷):有效载荷包含了具体的用户信息,如用户ID、用户名、角色等,也可以包含自定义的其他信息。这些信息以 JSON 格式进行编码,并且同样经过 Base64URL 编码,形成 JWT 的第二部分。Payload 中的声明可以分为三类:Reserved claims(标准声明)、Private claims(私有声明)和Public claims(公共声明)。

Signature(签名):签名是 JWT 的第三部分,它使用 Header 和 Payload 中的数据以及一个密钥来生成。签名的目的是保证消息没有被篡改,并且只能被服务器端识别和验证。签名也是通过特定的算法(如HMACSHA256)生成的,并会附加到JWT的末尾。

1.2 JWT 的工作原理

在用户登录后,系统会生成一个 JWT 返回给用户。用户的每次请求都会携带这个 JWT,通常将其放在 HTTP 请求的头部(如Authorization头部,使用Bearer模式)。服务器在接收到请求后,会验证 JWT 的签名以确认其完整性和来源,并根据 JWT 中的信息来认证用户或授权用户对资源的访问。

1.3 JWT 的优点

简洁和紧凑:JWT 是一个字符串,不占空间,传输速度快。

自包含:JWT 包含了用户信息和签名,服务器端不需要再查询数据库或其他存储来获取用户信息,实现了去中心化的验证。

跨语言支持:由于 JWT 是基于标准的 JSON 格式和 Base64URL 编码实现的,因此它可以在不同的平台和语言之间进行传输和解析。

安全性:在生成 JWT 签名时使用了加密算法,保证了 JWT 数据的安全性和完整性。然而,需要注意的是,JWT 本身不提供端到端的加密,因此不应存储敏感信息(如密码)。为了提高安全性,可以使用 JSON Web Encryption(JWE)对 JWT 进行加密。

1.4 JWT 的应用场景

JWT 广泛应用于现代 Web 应用程序中,特别是在身份验证和授权方面。以下是一些常见的应用场景:

单点登录:JWT 可以用于实现单点登录功能,用户只需登录一次即可在不同的系统或应用之间无缝切换。

跨域身份验证:JWT 可以在不同的域或子域之间传输用户身份信息,实现跨域的身份验证。

API安全认证:JWT 可以用于 API 的安全认证,确保只有合法的用户才能访问受保护的资源。

1.5 JWT 的安全性注意事项

尽管 JWT 提供了一些安全性,但其安全性也取决于如何使用和实现它。以下是一些关于 JWT 安全性的注意事项:

始终使用 HTTPS 协议:为了确保 JWT 在传输过程中的安全性,应始终使用 HTTPS 协议来传输 JWT。这有助于防止中间人攻击和窃听。

正确存储 JWT:在客户端,最常见的 JWT 存储方法是使用 cookie 或 localStorage。cookie 相对更安全,尤其是使用 HttpOnly 和 Secure 标志时。HttpOnly 标志可以防止 JavaScript 访问 cookie,降低了跨站脚本(XSS)攻击的风险;而 Secure 标志则确保 cookie 仅通过 HTTPS 传输,降低了中间人攻击的风险。

设置合理的有效期:JWT 的有效期应尽可能短,以减少攻击者利用窃取的令牌的时间。通常,JWT 应具有较短的生存时间(如15分钟),并使用刷新令牌在需要时更新。

避免在 JWT 中存储敏感信息:由于 JWT 在客户端和服务器之间传输时可能会被拦截或篡改,因此应避免在 JWT 中存储敏感信息(如密码)。如果需要传输敏感信息,请使用加密方法(如JWE)对JWT进行加密。

2、JWT 实现 Token 认证机制

【示例】使用 JWT 生成 Token 与 验证 Token。 

(1)添加 Maven 依赖

在项目的 pom.xml 配置文件中添加 JWT 依赖。

<!-- JWT 依赖 -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.4.0</version>
</dependency>

(2)创建工具类

 在 util 目录下,创建 JwtUtil 类(JWT 工具类)。

package com.pjb.util;
 
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
 
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
 
/**
 * JWT 工具类
 * @author pan_junbiao
 **/
public class JwtUtil
{
    //密钥
    private final static String SECRET_KEY = "123456789";
 
    /**
     * 创建 JWT 令牌
     */
    public static String createToken(Map<String, Object> payloadClaims)
    {
        //创建 Header(头部)内容
        HashMap<String, Object> headerMap = new HashMap<>();
 
        //令牌过期时间
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND, 60); //60秒
 
        //生成 JWT 令牌
        String token = JWT.create()
                .withExpiresAt(instance.getTime())     //设置令牌过期时间
                .withHeader(headerMap)                 //设置 Header(头部)
                .withPayload(payloadClaims)            //设置 Payload(载荷)
                .sign(Algorithm.HMAC256(SECRET_KEY));  //设置 Signature(签名)
 
        //返回结果
        return token;
    }
 
    /**
     * 验证 JWT 令牌
     */
    public static DecodedJWT verifierToken(String jwtToken)
    {
        try
        {
            //创建验证对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET_KEY)).build();
 
            //验证令牌
            DecodedJWT decodedJWT = jwtVerifier.verify(jwtToken);
 
            //返回结果
            return decodedJWT;
        } catch (SignatureVerificationException ex)
        {
            System.out.println("无效的签名");
            ex.printStackTrace();
        } catch (TokenExpiredException ex)
        {
            System.out.println("Token已过期");
            ex.printStackTrace();
        } catch (AlgorithmMismatchException ex)
        {
            System.out.println("验证的算法不一致");
            ex.printStackTrace();
        } catch (Exception ex)
        {
            System.out.println("Token验证发生异常");
            ex.printStackTrace();
        }
        return null;
    }
}

(3)执行方法

使用 JWT 生成 Token 与 验证 Token。

/**
 * 使用 JWT 实现 Token 认证机制
 */
@Test
public void testJwtToken()
{
    //创建数据(Payload 载荷)
    Map<String, Object> payloadClaims = new HashMap<>();
    payloadClaims.put("userId",1);
    payloadClaims.put("userName","pan_junbiao的博客");
    payloadClaims.put("blogInfo","您好,欢迎访问 pan_junbiao的博客");
    payloadClaims.put("blogUrl","https://blog.csdn.net/pan_junbiao");
 
    // 1、创建 JWT 令牌
    String token = JwtUtil.createToken(payloadClaims);
 
    // 2、验证 JWT 令牌
    DecodedJWT decodedJWT = JwtUtil.verifierToken(token);
    if(decodedJWT == null)
    {
        System.out.println("验证 JWT 令牌失败");
        return;
    }
 
    //打印结果
    System.out.println("生成Token:" + token);
    System.out.println("验证Token:" + (decodedJWT != null));
    System.out.println("Token过期时间:" + decodedJWT.getExpiresAtAsInstant());
    System.out.println("用户编号:" + decodedJWT.getClaim("userId").asInt());
    System.out.println("用户名称:" + decodedJWT.getClaim("userName").asString());
    System.out.println("博客信息:" + decodedJWT.getClaim("blogInfo").asString());
    System.out.println("博客地址:" + decodedJWT.getClaim("blogUrl").asString());
}

执行结果:

以上就是Java如何使用JWT实现Token认证机制的详细内容,更多关于Java JWT实现Token认证的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文