Java如何使用JWT实现Token认证机制
作者:pan_junbiao
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认证的资料请关注脚本之家其它相关文章!
