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认证的资料请关注脚本之家其它相关文章!