在构建现代Web应用程序时,安全性是一个不可或缺的要素。JSON Web Token(JWT)提供了一种简洁的方式来保护我们的RESTful接口。在本篇博客中,我们将一步步探索如何在Spring Boot应用中整合JWT,确保你的API安全、高效且易于管理。
JWT简介
JWT(JSON Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。这些信息可以被验证和信任,因为它是数字签名的。
为什么选择JWT
对于Web应用程序,尤其是当涉及到单页面应用(SPA)时,JWT提供了一种有效的认证机制。与传统的Session认证相比,JWT是无状态的,不需要在服务器上存储用户的状态信息,这使得它非常适合于分布式微服务架构。
Spring Boot中整合JWT
在Spring Boot中整合JWT,我们需要完成以下步骤:
- 添加依赖
- 配置JWT库
- 实现JWT认证过滤器
- 配置Spring Security
- 测试保护的API
实战演练:构建一个示例应用
让我们通过构建一个简单的Spring Boot应用来演示JWT的整合过程。
添加依赖
首先,在你的pom.xml
中添加以下依赖:
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 其他依赖 -->
</dependencies>
配置JWT库
接下来,我们需要创建一个工具类来生成和解析JWT:
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtil {
private static final String KEY = "mySecretKey";
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时有效期
.signWith(SignatureAlgorithm.HS512, KEY)
.compact();
}
public static String validateTokenAndGetSubject(String token) {
return Jwts.parser()
.setSigningKey(KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
实现JWT认证过滤器
现在,我们创建一个JWT认证过滤器来验证令牌的有效性:
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
String username = JwtUtil.validateTokenAndGetSubject(token);
if (username != null) {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
filterChain.doFilter(request, response);
}
}
配置Spring Security
我们需要配置Spring Security来使用我们的JWT过滤器:
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/public").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()));
}
}
测试保护的API
最后,我们创建一个受保护的API端点和一个公开端点作为测试:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/api/public")
public String publicEndpoint() {
return "Public content";
}
@GetMapping("/api/private")
public String privateEndpoint() {
return "Private content";
}
}
JWT的最佳实践
- 保持密钥的安全
- 设置合理的过期时间
- 处理令牌失效的情况
- 只通过HTTPS传输JWT
总结
通过这个简单的例子,我们看到了如何在Spring Boot应用程序中使用JWT进行安全认证。JWT的整合提高了我们API的安全性,同时保持了良好的性能和可扩展性。如果你想要构建一个安全且现代的Web应用程序,那么Spring Boot和JWT无疑是你的不二之选。