下面是一个使用 Spring Boot、Spring Security 和 JWT 的简单示例,用于保护 REST 端点:
- 添加依赖
在 pom.xml
文件中添加 Spring Security 和 JWT 依赖:
<dependencies>
<!-- ...其他依赖... -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<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>
</dependencies>
- 配置 Spring Security
创建一个配置类 SecurityConfig
,继承 WebSecurityConfigurerAdapter
,并配置 Spring Security:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
- 创建 JWT 工具类
创建一个 JwtUtil
类,用于生成和验证 JWT 令牌:
@Component
public class JwtUtil {
private final String SECRET_KEY = "your_secret_key";
private final long EXPIRATION_TIME = 86400000L; // 1 day
public String generateToken(String username) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + EXPIRATION_TIME);
return Jwts.builder()
.setSubject(username)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(Keys.hmacShaKeyFor(SECRET_KEY.getBytes()))
.compact();
}
public String getUsernameFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(SECRET_KEY.getBytes()))
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(Keys.hmacShaKeyFor(SECRET_KEY.getBytes()))
.build()
.parseClaimsJws(token);
return true;
} catch (JwtException e) {
return false;
}
}
}
- 创建 JWT 认证过滤器
创建一个 JwtAuthenticationFilter
类,继承 OncePerRequestFilter
,用于验证 JWT 令牌:
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && jwtUtil.validateToken(token)) {
String username = jwtUtil.getUsernameFromToken(token);
if (username != null) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
}
- 创建认证端点
创建一个 AuthenticationController
,用于用户登录并返回 JWT 令牌:
@RestController
@RequestMapping("/api")
public class AuthenticationController {
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/authenticate")
public ResponseEntity<String> authenticate(@RequestBody UserCredentials userCredentials) {
// 在这里添加用户验证逻辑,例如查询数据库验证用户名和密码
// 如果验证通过,生成 JWT 令牌并返回
String token = jwtUtil.generateToken(userCredentials.getUsername());
return ResponseEntity.ok(token);
}
}
- 创建用户凭据类
创建一个 UserCredentials
类,用于接收客户端发送的用户名和密码:
public class UserCredentials {
private String username;
private String password;
// 构造方法、getter 和 setter 省略
}
现在,你可以使用 /api/authenticate
端点进行登录,获取 JWT 令牌。在访问受保护的 REST 端点时,需要在请求头中添加 Authorization
字段,值为 Bearer {your_jwt_token}
。JWT 认证过滤器会验证令牌并设置用户身份。