Spring Boot整合JWT(JSON Web Token)生成Token与验证
在现代应用中,身份验证是一个非常重要的部分。随着RESTful API的广泛使用,Token(令牌)机制逐渐成为一种主流的身份验证方式。JWT(JSON Web Token)就是其中一种流行的Token机制,它通过对用户的身份进行编码,方便安全地在客户端和服务器之间传递信息。本文将介绍如何在Spring Boot中整合JWT,包括Token的生成和验证。
一、环境准备
在开始之前,请确保你已经安装了JDK和Maven,并创建了一个Spring Boot项目。你可以使用Spring Initializr来快速生成项目基础结构,并添加以下依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
二、生成JWT Token
首先,我们需要创建一个JWT工具类,用于生成和解析Token。
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtUtil {
private String secretKey = "your_secret_key"; // 密钥,可以从配置文件中读取
private long expiration = 3600000; // 一小时有效期
// 生成Token
public String generateToken(String username) {
long now = System.currentTimeMillis();
Date issuedAt = new Date(now);
Date expiryDate = new Date(now + expiration);
JwtBuilder builder = Jwts.builder()
.setSubject(username)
.setIssuedAt(issuedAt)
.setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS512, secretKey);
return builder.compact();
}
// 验证Token
public Claims validateToken(String token) {
JwtParser parser = Jwts.parser().setSigningKey(secretKey);
return parser.parseClaimsJws(token).getBody();
}
}
三、配置安全策略
接下来,我们需要配置Spring Security,使其能够使用我们生成的JWT Token。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()));
}
}
四、用户登录和Token返回
我们需要创建一个Controller类,该类处理用户登录并返回JWT Token。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;
@RestController
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService;
@PostMapping("/login")
public String login(@RequestBody UserLoginDto userLoginDto) {
// 验证用户
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(userLoginDto.getUsername(), userLoginDto.getPassword())
);
// 生成并返回Token
return jwtUtil.generateToken(userLoginDto.getUsername());
}
}
class UserLoginDto {
private String username;
private String password;
// getters and setters
}
五、验证Token
为了验证JWT Token,我们需要添加一个过滤器,该过滤器将在每次请求时检查Token。
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final AuthenticationManager authenticationManager;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
// 从请求头中获取Token
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
Claims claims = jwtUtil.validateToken(token);
if (claims != null) {
String username = claims.getSubject();
// 根据用户名加载用户信息
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 设置安全上下文
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()));
}
}
filterChain.doFilter(request, response);
}
}
六、总结
通过以上步骤,我们实现了一个简单的JWT身份验证系统。用户通过登录接口(/login)获取Token,该Token在后续请求中作为Authorization头的内容进行验证。这样,我们就实现了安全的身份验证。
在实际生产环境中,请务必注意密钥的安全管理、Token的失效机制、以及HTTPS的使用等安全措施。希望本文对你理解Spring Boot整合JWT有帮助!