JWT - 令牌认证(认证流程和原理、Jwt 工具类、搭配 Redis 使用)
JWT(JSON Web Token)是一种用于双方之间传递安全信息的简洁的、URL安全的表示方法。
以下是使用JWT的一般流程:
- 用户登录:用户使用用户名和密码登录。
- 验证凭据:服务器验证用户名和密码。
- 创建JWT:服务器验证成功后,创建一个JWT。
- 返回JWT:服务器返回JWT给客户端。
- 客户端存储JWT:客户端通常将JWT存储在localStorage或sessionStorage中。
- 后续请求:客户端在后续请求中将JWT添加到请求头中。
- 服务器验证JWT:服务器检查请求头中的JWT,如果JWT有效,则提供访问权限。
JWT结构通常如下:
Header.Payload.Signature
Header通常指定签名算法:
{
"alg": "HS256",
"typ": "JWT"
}
Payload包含实际的声明:
{
"iss": "Issuer",
"sub": "Subject",
"aud": "Audience",
"exp": "Expiration Time",
"nbf": "Not Before",
"iat": "Issued At",
"jti": "JWT ID"
}
Signature通过以下方式创建:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
以下是一个简单的Java JWT工具类示例:
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.Claims;
public class JwtUtil {
private static final String SECRET_KEY = "verySecret"; // 应该是一个复杂的密钥
public static String generateToken(User user) {
return Jwts.builder()
.setSubject(user.getUsername())
.setExpiration(new Date(System.currentTimeMillis() + 864000000)) // 有效期10天
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public static boolean validateToken(String token, UserDetails userDetails) {
String username = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
private static boolean isTokenExpired(String token) {
Date expiration = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getExpiration();
return expiration.before(new Date());
}
}
在与Redis结合使用时,可以在用户登录时创建JWT并将其存储在Redis中,并在后续请求中验证Redis中的JWT是否有效。
public String login(User user) {
String token = JwtUtil.generateToken(user);
redisTemplate.opsForValue().set(token, user.getUsername(), 10, TimeUnit.DAYS);
return token;
}
public boolean validateToken(String token) {
boolean isTokenValid = false;
String username = (String) redisTemplate.opsForValue().get(token);
if (username != null && !username.isEmpty()) {
isTokenValid = true;
评论已关闭