JWT讲解(一)

news/2025/2/19 17:47:25/

1.简介

JWT(JSON Web Token)是一种用于在不同应用之间安全传输信息的开放标准(RFC 7519)。JWT通常用于Web应用程序和API中的身份验证和授权目的。

JWT由三个部分组成:头部(header)、负载(payload)和签名(signature)。头部通常包含关于令牌类型和使用的签名算法的信息。负载包含有关用户或其他传输数据的声明或陈述。这些声明可以包括用户的身份、权限和其他元数据等信息。签名用于验证令牌的完整性,确保它没有被篡改。

以下是一个JWT令牌的示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

在这个示例中,令牌由三部分组成,以点号(‘.’)分隔。第一部分是头部,第二部分是负载,第三部分是签名。每个部分都经过base64编码,但令牌本身并没有被加密。需要注意的是,JWT不应包含敏感信息,因为任何具有令牌访问权限的人都可以对其进行解码。

JWT通常在身份验证流程中使用,用户登录到Web应用程序时会发出JWT。在成功认证后,服务器会向客户端发出JWT,其中包含相关用户信息,并由服务器使用一个密钥进行签名。然后客户端在后续请求中包含这个JWT,服务器可以验证令牌的真实性并根据令牌中的声明授予对受保护资源的访问权限。

服务器可以解码JWT,使用密钥验证签名,并检查声明以确定用户是否具有访问特定资源的必要权限。如果令牌有效且用户被授权,服务器会相应地响应客户端的请求。

2.JWT的创建和校验

当在Java中实现JWT的创建和校验时,可以使用第三方库,如jjwt(Java JWT)来简化操作。以下是JWT的创建和校验的详细实现示例:

首先,您需要在项目中添加 jjwt 依赖。在 Maven 项目中,可以将以下依赖添加到 pom.xml 文件中:

<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.2</version>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.2</version><scope>runtime</scope>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.2</version><scope>runtime</scope>
</dependency>

创建JWT的示例代码如下:

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import java.util.Date;public class JwtUtil {private static final String SECRET_KEY = "your-secret-key";private static final long EXPIRATION_TIME = 3600000; // 1 hour/*** 创建JWT** @param userId 用户ID* @param role   用户角色* @return JWT字符串*/public static String generateToken(String userId, String role) {Date now = new Date();Date expiration = new Date(now.getTime() + EXPIRATION_TIME);// 构建JWT并返回JWT字符串return Jwts.builder().setSubject(userId) // 设置JWT的主题(Subject).claim("role", role) // 添加自定义声明(Claim).setIssuedAt(now) // 设置JWT的签发时间(Issued At).setExpiration(expiration) // 设置JWT的过期时间.signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 使用HS256算法和密钥对JWT进行签名.compact(); // 生成JWT字符串}
}

在上述示例中,我们使用io.jsonwebtoken.Jwts类创建JWT。我们指定了主题(subject)、声明(claim)、发行时间(issuedAt)和过期时间(expiration)。然后,我们使用signWith方法使用秘钥(密钥)和所选的签名算法对JWT进行签名。
接下来,让我们看一下如何校验JWT的示例代码:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;public class JwtUtil {private static final String SECRET_KEY = "your-secret-key";/*** 校验JWT的有效性** @param jwt JWT字符串* @return 校验结果,true表示有效,false表示无效*/public static boolean validateToken(String jwt) {try {Jws<Claims> claims = Jwts.parserBuilder().setSigningKey(SECRET_KEY) // 设置用于校验签名的密钥.build().parseClaimsJws(jwt); // 解析JWT并获取包含声明的Jws对象// 校验通过return true;} catch (Exception e) {// 校验失败e.printStackTrace();return false;}}
}

在上述示例中,我们使用io.jsonwebtoken.Jwts类的parserBuilder方法创建一个JWT解析器,并使用给定的秘钥进行解析和验证。如果JWT有效且签名正确,解析过程将不会抛出异常。

需要注意的是,在实际应用中,为了更好的安全性,建议使用更长的和随机的秘钥,并妥善保管秘钥,不要将其直接硬编码在代码中。

3. JWT登录权限案例

下面是一个使用 Java JWT(JSON Web Token)实现登录权限的详细案例。

首先,需要确保已经在项目中添加了适当的依赖项,以使用 JWT。常用的 JWT 库有 jjwt 和 Nimbus-JOSE-JWT,你可以根据自己的喜好选择其中之一。

创建一个 JwtUtil 类,用于生成和验证 JWT。

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;import java.security.Key;
import java.util.Date;public class JwtUtil {private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);private static final long EXPIRATION_TIME = 86400000; // 24 小时/*** 生成 JWT** @param username 用户名* @return JWT*/public static String generateToken(String username) {Date now = new Date();Date expirationDate = new Date(now.getTime() + EXPIRATION_TIME);return Jwts.builder().setSubject(username).setIssuedAt(now).setExpiration(expirationDate).signWith(SECRET_KEY).compact();}/*** 从 JWT 中提取用户名** @param token JWT* @return 用户名*/public static String getUsernameFromToken(String token) {Claims claims = Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token).getBody();return claims.getSubject();}/*** 验证 JWT 的有效性** @param token JWT* @return 验证结果,true 表示有效,false 表示无效*/public static boolean validateToken(String token) {try {Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token);return true;} catch (Exception e) {return false;}}
}

创建一个简单的登录接口 LoginController,用于生成 JWT:

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class LoginController {@PostMapping("/login")public String login(@RequestBody LoginRequest loginRequest) {// 根据用户名和密码验证用户if (authenticate(loginRequest.getUsername(), loginRequest.getPassword())) {// 生成 JWTString token = JwtUtil.generateToken(loginRequest.getUsername());return token;} else {return "Invalid credentials.";}}private boolean authenticate(String username, String password) {// 在这里编写你的身份验证逻辑// 可以通过查询数据库、调用外部认证服务等方式进行验证// 这里只是一个简单的示例,模拟用户名为 "admin",密码为 "password" 的用户进行验证if ("admin".equals(username) && "password".equals(password)) {return true;} else {return false;}}
}

创建一个受保护的接口 ProtectedController,只允许授权用户访问:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ProtectedController {@GetMapping("/protected")public String protectedEndpoint(@RequestHeader("Authorization") String authorizationHeader) {String token = authorizationHeader.replace("Bearer ", "");if (JwtUtil.validateToken(token)) {String username = JwtUtil.getUsernameFromToken(token);return "Hello, " + username + "! This is a protected endpoint.";} else {return "Invalid token.";}}
}

在上述代码中,JwtUtil 类提供了生成和验证 JWT 的方法。generateToken 方法根据给定的用户名生成 JWT,getUsernameFromToken 方法从给定的 JWT 中提取用户名,validateToken 方法验证 JWT 的有效性。

LoginController 的 login 方法接收用户名和密码,调用 authenticate 方法进行身份验证。如果验证通过,则使用 JwtUtil.generateToken 方法生成 JWT,并将其返回给客户端。

ProtectedController 的 protectedEndpoint 方法


http://www.ppmy.cn/news/449613.html

相关文章

C++字节序测试

下面是一个简单的字节序测试示例&#xff0c;可以用来检查当前计算机的字节序&#xff1a; &#xff08;本人所写的所有博客知识点示例均可上机测试&#xff0c;需要可以收藏&#xff09; #include <iostream>int main() {uint32_t num 0x12345678;uint8_t* ptr reint…

Dell Inspiron13 7000常用设置

关闭F1~F12的电脑自带功能 自带功能会使一些快捷键没发正常使用&#xff0c;同时按下Fn Esc关闭,再按一次打开功能。关闭触屏功能 桌面右键我的电脑&#xff0c;选择-管理&#xff0c;选择-设备管理器&#xff0c;选择-人体学输入设备&#xff0c;选择-符合HID标准的触摸屏&am…

Dell灵越燃7000网络驱动被误删后无法安装解决方案

使用驱动精灵网卡版&#xff0c;360驱动大师网卡版&#xff0c;驱动人生万能网卡版之后还无法解决&#xff0c;且出现错误值为56的解决方法&#xff1a; 下载一个CClear&#xff1a; http://soft.onlinedown.net/soft/46616.htm 不要购买任何东西&#xff0c;不要注册&#xff…

Dell Inspiron 15 7000 Gaming (BIOS :1.6.0)Windows10 安装 Ubuntu 16.04

1. 笔记本配置 win R 打开运行并输入dxdiag&#xff1b; 出现directX&#xff1a; 2. 步骤 按照网上教程即可; 3.问题 &#xff08;1&#xff09;必须禁用独立显卡&#xff01;禁用方法可以在开机启动项中添加语句&#xff0c;开机时按e&#xff0c;在倒数第二行加上acpi o…

AI催生电影新纪元?大咖们纷纷发声|瞩目上影节

AI催生电影新纪元&#xff1f;大咖们纷纷发声&#xff5c;瞩目上影节 听说“谁懂AI&#xff0c;谁股票就飙高”。博纳影业集团创始人兼总经理于冬一句话引得会场爆笑连连。 AI成为今年上海国际电影节热议话题之一。在金爵电影论坛开幕论坛上&#xff0c;于冬、中国电影股份有限…

戴尔DELLEMC服务器重装CentOS 7系统

文章目录 一、下载镜像二、制作U盘启动盘三、开始安装四、解决问题五、参考 一、下载镜像 CentOS 7—阿里云开源镜像站 CentOS 7—vault开源镜像站 二、制作U盘启动盘 三、开始安装 开机或者reboot按F11开始 四、解决问题 dracut-initqueue timeout 在Install CentOS 7的…

【win10小技巧】解决windows 10睡眠后再唤醒,就会自动关机并重启的问题(仅限Dell)

不管是左下角的睡眠选项&#xff0c;还是直接合上笔记本的盖子&#xff0c;计算机都应该是进入了睡眠状态。之后再按键盘上的任意键&#xff0c;计算机都应该会直接唤醒&#xff0c;唤醒后的计算机状态跟睡眠前的计算机状态是一毛一样的。 但是我的笔记本就是这么的不听话&…

dell 燃 7000 系列 7460/7560 禁用触控板 触摸板

一&#xff0c;禁用dell燃7000触控板 博主用的是dell 7560 win10,一直没找到禁用触控板的选项 后来在设备管理器中找到了&#xff0c; 1.winx调出快捷菜单-->M键是"设备管理器” 2.人体学输入设备->触摸板->禁用 3.如图,把I2C HID设备禁用掉: 二&#xff0c;禁用…