JWT入门
一、初识JWT:新时代的身份认证方案
在分布式系统成为主流的今天,传统的Session认证方式逐渐显露出局限性。JWT(JSON Web Token)作为现代Web开发的认证新标准,凭借其无状态、跨域友好和安全性等特性,正在成为开发者构建认证系统的首选方案。
1.1 传统认证的痛点
服务端需要存储会话信息
跨域资源共享(CORS)问题
移动端支持不够友好
1.2 JWT核心优势
无状态:服务端无需存储会话信息
自包含:用户信息直接存储在Token中
跨平台:天然支持移动端和微服务架构
二、JWT技术解剖
2.1 令牌结构
典型的JWT格式:header.payload.signature
2.1.1 Header头部
{
"alg": "HS256",
"typ": "JWT"
}
alg:签名算法(如HS256,RS256)
typ:令牌类型
2.1.2 Payload载荷
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
注册声明(建议但不强制):
iss: 签发者
exp: 过期时间
sub: 主题
2.1.3 Signature签名
使用Base64Url编码的头部和载荷,结合密钥通过指定算法生成:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
三、Java实战:Spring Boot集成JWT
3.1 环境搭建
pom.xml添加依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
3.2 核心工具类实现
public class JwtUtil {
private static final String SECRET_KEY = "your-256-bit-secret";
private static final long EXPIRATION = 86400000; // 24小时
public static String generateToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public static boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
// 异常处理逻辑
return false;
}
}
}
3.3 Spring Security整合配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
public class JwtFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain)
throws ServletException, IOException {
String token = extractToken(request);
if (token != null && JwtUtil.validateToken(token)) {
Authentication auth = createAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
}
四、最佳实践与安全策略
4.1 安全注意事项
密钥管理:使用至少256位的安全密钥
HTTPS:必须强制使用加密传输
存储方案:避免LocalStorage,推荐使用HttpOnly Cookie
令牌时效:设置合理的过期时间(建议≤24小时)
4.2 性能优化技巧
使用非对称加密(RS256)提升验证效率
采用黑名单机制处理提前注销
配合Redis实现令牌刷新机制
五、真实业务场景应用
5.1 用户登录流程
@PostMapping("/login")
public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest request) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.getUsername(),
request.getPassword()));
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String jwt = JwtUtil.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(jwt));
}
5.2 接口权限控制
@GetMapping("/profile")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<UserProfile> getUserProfile() {
String username = SecurityContextHolder.getContext()
.getAuthentication().getName();
// 获取用户信息逻辑
return ResponseEntity.ok(userProfile);
}
结语:把握技术本质
JWT不是银弹,但正确使用时确实能极大提升系统安全性和扩展性。
深入理解各种签名算法的适用场景
定期轮换加密密钥
监控令牌使用情况,及时调整安全策略
结合具体业务需求设计声明(claims)结构
通过持续实践和优化,JWT将成为您构建现代Web应用的强大助力。