前言:
JWT,也就是JSON Web Token,通常用于身份验证和授权。用户登录后,服务器生成一个JWT,客户端之后每次请求都带着这个Token,服务器验证Token的有效性来鉴权。
完整示例:
第一步:添加依赖(pom.xml)
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JJWT 库 -->
<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>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
第二步:创建 JWT 工具类
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Date;
@Component
public class JwtUtil {
// 密钥(示例代码硬编码,实际应存储在安全位置)
private final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
// Token 有效期(30分钟)
private final long EXPIRATION_TIME = 1800000;
// 生成 JWT
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SECRET_KEY)
.compact();
}
// 验证并解析 JWT
public Claims parseToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(SECRET_KEY)
.build()
.parseClaimsJws(token)
.getBody();
}
// 检查 Token 是否过期
public boolean isTokenExpired(String token) {
return parseToken(token).getExpiration().before(new Date());
}
}
第三步:创建登录接口和受保护接口
import org.springframework.web.bind.annotation.*;
@RestController
public class AuthController {
private final JwtUtil jwtUtil;
public AuthController(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
// 登录接口(模拟)
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
// 这里应该验证用户名密码(示例直接返回Token)
return jwtUtil.generateToken(username);
}
// 需要鉴权的接口
@GetMapping("/secure")
public String secureEndpoint() {
return "访问受保护资源成功";
}
}
第四步:创建 JWT 过滤器
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class JwtFilter extends OncePerRequestFilter {
private final JwtUtil jwtUtil;
public JwtFilter(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
try {
Claims claims = jwtUtil.parseToken(token);
if (jwtUtil.isTokenExpired(token)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token已过期");
return;
}
// 可以在此处将用户信息存入请求上下文
request.setAttribute("username", claims.getSubject());
} catch (JwtException e) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "无效Token");
return;
}
} else {
// 放行登录接口
if (!request.getServletPath().equals("/login")) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "缺少Token");
return;
}
}
filterChain.doFilter(request, response);
}
}
第五步:配置 Spring Boot 应用
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class JwtDemoApplication {
public static void main(String[] args) {
SpringApplication.run(JwtDemoApplication.class, args);
}
@Bean
public FilterRegistrationBean<JwtFilter> jwtFilter(JwtUtil jwtUtil) {
FilterRegistrationBean<JwtFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new JwtFilter(jwtUtil));
registrationBean.addUrlPatterns("/secure");
return registrationBean;
}
}
使用示例:
-
启动应用后,发送登录请求获取Token:
curl -X POST http://localhost:8080/login?username=admin&password=123
-
使用返回的Token访问受保护接口:
curl -H "Authorization: Bearer <your_token>" http://localhost:8080/secure
注意事项:
-
实际生产环境中:
-
密钥应存储在安全位置(如配置中心)
-
密码需要加密存储和验证
-
需要使用HTTPS保证传输安全
-
需要考虑Token刷新机制
-
-
该示例使用HS256算法,如需更安全可选择RS256算法
-
可根据需要添加更多用户信息到Token Claims中