目录
- 使用springboot解释什么是jwt
- 简介
- 组成结构
- 在springboot中的作用
- 1. 添加依赖 在`pom.xml`文件中添加以下依赖
- 2. 配置JWT 在Spring Boot的配置文件中配置JWT的相关参数,例如密钥、过期时间等:
- 3. 创建JWT工具类 创建一个JWT工具类,用于生成和解析JWT:
- 4. 创建控制器 创建一个控制器,用于生成JWT和验证JWT:
- 5. 测试接口 使用Postman等工具测试接口
使用springboot解释什么是jwt
简介
JWT全称为JSON Web Token,是一种基于JSON格式的轻量级的身份认证和授权机制。它由三部分组成,分别是头部(Header)、载荷(Payload)和签名(Signature),通常使用点号(.)将这三部分连接起来形成一个字符串。其中,头部通常包含加密算法和token类型等信息,载荷通常包含用户信息和权限等数据,签名则是对头部和载荷的加密结果。JWT常用于Web应用的身份认证和授权,客户端通过在请求头中携带JWT向服务器进行身份验证并获取资源。由于JWT是无状态的,因此可以实现跨域请求和分布式系统的身份认证和授权。
组成结构
jwt令牌由三个部分组成,分别是:
header:令牌头部,记录了整个令牌的类型和签名算法
payload:令牌负荷,记录了保存的主体信息,比如你要保存的用户信息就可以放到这里
signature:令牌签名,按照头部固定的签名算法对整个令牌进行签名,该签名的作用是:保证令牌不被伪造和篡改
它们组合而成的完整格式是:header.payload.signature
下面是一个具体的JWT示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
这个JWT由三部分组成,用点号(.)分隔:
-
头部(Header):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
-
载荷(Payload):
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
-
签名(Signature):
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
其中,头部和载荷都是使用Base64Url编码后的JSON字符串,可以使用Base64Url解码得到原始的JSON数据。例如,上面的头部可以解码为以下JSON格式:
{
"alg": "HS256",
"typ": "JWT"
}
这表示该JWT使用HS256算法进行签名,并且类型为JWT。而载荷可以解码为以下JSON格式:
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
这表示该JWT的主题为"1234567890",用户名为"John Doe",签发时间为2018年1月18日 22:23:42。而签名则是对头部和载荷的加密结果,可以使用密钥进行解密得到原始数据。
在springboot中的作用
在Spring Boot中使用JWT的具体案例如下:
1. 添加依赖 在pom.xml
文件中添加以下依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2. 配置JWT 在Spring Boot的配置文件中配置JWT的相关参数,例如密钥、过期时间等:
jwt:
secret: mySecretKey
expiration: 3600
3. 创建JWT工具类 创建一个JWT工具类,用于生成和解析JWT:
@Component
public class JwtUtils {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private long expiration;
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put("sub", userDetails.getUsername());
claims.put("iat", new Date());
claims.put("exp", new Date(System.currentTimeMillis() + expiration * 1000));
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public String getUsernameFromToken(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject();
}
public boolean validateToken(String token, UserDetails userDetails) {
String username = getUsernameFromToken(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
private boolean isTokenExpired(String token) {
Date expirationDate = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getExpiration();
return expirationDate.before(new Date());
}
}
这个工具类中包含了生成JWT、解析JWT和校验JWT的方法。其中,生成JWT时将用户信息存储在载荷中,解析JWT时可以获取到载荷中存储的用户信息。
4. 创建控制器 创建一个控制器,用于生成JWT和验证JWT:
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtils jwtUtils;
@PostMapping("/login")
public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtUtils.generateToken((UserDetails) authentication.getPrincipal());
return ResponseEntity.ok(new JwtResponse(jwt));
}
@GetMapping("/user")
public ResponseEntity<?> getUser(@RequestHeader("Authorization") String token) {
String username = jwtUtils.getUsernameFromToken(token.substring(7));
User user = new User(username);
return ResponseEntity.ok(user);
}
}
这个控制器中包含了一个登录接口和一个获取用户信息的接口。登录接口会校验用户名和密码,并生成JWT返回给客户端;获取用户信息的接口会根据JWT中的用户信息返回相应的用户信息。
5. 测试接口 使用Postman等工具测试接口
- 登录接口:发送POST请求到
/auth/login
,请求体为JSON格式的登录信息:
{
"username": "admin",
"password": "admin"
}
如果登录成功,会返回如下格式的JWT
{
"token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImlhdCI6MTYzOTU5Mzg5MiwiZXhwIjoxNjM5NjAzODkyfQ.7jKbW8uZwVnNpDxgFv7Ll-W1eQ2m9y9XzjvP8vejJZw"
}
获取用户信息接口:发送GET请求到/auth/user
,请求头中携带JWT:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImlhdCI6MTYzOTU5Mzg5MiwiZXhwIjoxNjM5NjAzODkyfQ.7jKbW8uZwVnNpDxgFv7Ll-W1eQ2m9y9XzjvP8vejJZw
如果JWT有效,会返回如下格式的用户信息:
{
"username": "admin"
}