简洁(Compact):JWT令牌可以在URL、POST参数、HTTP头部等多种方式传输,便于在各种场景下使用。
自包含(Self-contained):JWT令牌包含了所有用户所需的信息,避免了需要查询数据库的开销。
数字签名(Digital Signature):JWT令牌可以使用数字签名进行验证,确保数据的完整性和安全性。
用户登录时,服务器验证用户的身份,并生成JWT令牌。
服务器将JWT令牌返回给客户端,客户端在后续的请求中携带JWT令牌。
服务器在接收到带有JWT令牌的请求时,验证JWT令牌的有效性和完整性,并根据其中的信息进行相应的处理。
<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>
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Component
public class JwtTokenUtil {
// 从配置文件中读取密钥和过期时间
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
/**
* 生成JWT令牌
* @param username 用户名
* @return JWT令牌
*/
public String generateToken(String username) {
// 设置JWT令牌中的信息
Map<String, Object> claims = new HashMap<>();
claims.put("sub", username);
claims.put("created", new Date());
// 生成JWT令牌
return Jwts.builder()
.setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
/**
* 从JWT令牌中获取用户名
* @param token JWT令牌
* @return 用户名
*/
public String getUsernameFromToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
/**
* 从JWT令牌中获取过期时间
* @param token JWT令牌
* @return 过期时间
*/
public Date getExpirationDateFromToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
return claims.getExpiration();
}
/**
* 验证JWT令牌的有效性
* @param token JWT令牌
* @param username 用户名
* @return JWT令牌是否有效
*/
public boolean validateToken(String token, String username) {
String tokenUsername = getUsernameFromToken(token);
return (tokenUsername.equals(username) && !isTokenExpired(token));
}
/**
* 判断JWT令牌是否已过期
* @param token JWT令牌
* @return JWT令牌是否已过期
*/
private boolean isTokenExpired(String token) {
Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
}
import org.springframework.beans.factory.annotation.Autowired;
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 {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@PostMapping("/login")
public String login(@RequestBody User user) {
// 校验用户名和密码
// ...
// 生成JWT令牌
String token = jwtTokenUtil.generateToken(user.getUsername());
return token;
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ResourceController {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@GetMapping("/resource")
public String getResource(@RequestHeader("Authorization") String token) {
// 从JWT令牌中获取用户名
String username = jwtTokenUtil.getUsernameFromToken(token);
// 根据用户名获取资源
// ...
return "resource";
}
}