Spring Boot + JWT实现安全认证
在现代Web应用中,安全性是一个至关重要的方面。而JWT(JSON Web Token)是一种非常流行的实现用户认证和信息交换的方式。本文将介绍如何在Spring Boot应用中集成JWT,并提供相应的代码示例。
什么是JWT?
JWT(JSON Web Token)是一种开放标准(RFC 7519),它定义了一种紧凑且独立的方式,用于以JSON对象传递信息,信息可以被验证和信任。JWT的好处在于它可以方便地用于身份验证和信息交换,它具有以下特点:
- 紧凑性:JWT的大小相对较小,可以通过URL、POST参数或者HTTP头部传输。
- 自包含:JWT包含了用户的所有信息,避免了多次查询数据库。
- 安全性:通过签名可以确保JWT的完整性和有效性。
Spring Boot项目设置
首先,我们需要在Spring Boot项目中添加相关依赖。我们可以在pom.xml
文件中添加以下内容:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
生成JWT
我们需要创建一个JWT工具类来生成和解析JWT:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "your_secret_key"; // 秘钥
private static final long EXPIRATION = 864_000_00; // 过期时间,单位毫秒
// 生成JWT
public static String generateToken(String username) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder builder = Jwts.builder()
.setSubject(username)
.setIssuedAt(now)
.setExpiration(new Date(nowMillis + EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY);
return builder.compact();
}
// 验证JWT
public static Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
}
实现用户认证
接下来,我们需要实现一个简单的用户认证功能。可以创建一个控制器来处理登录请求:
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
// 此处应该查询数据库验证用户信息,这里为了简化直接返回token
if ("user".equals(username) && "password".equals(password)) {
return JwtUtil.generateToken(username);
} else {
throw new RuntimeException("用户名或密码错误");
}
}
}
添加过滤器验证JWT
为了保护需要认证的接口,我们可以添加JWT过滤器,验证请求中的JWT:
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)
throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
// 检查header中是否包含Bearer Token
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7); // 获取token
try {
Claims claims = JwtUtil.parseToken(token);
// 可以将用户信息存储在上下文中,以备后用
request.setAttribute("username", claims.getSubject());
} catch (Exception e) {
throw new RuntimeException("无效的token");
}
}
filterChain.doFilter(request, response); // 继续过滤链
}
}
配置Spring Security
最后,我们需要配置Spring Security,添加自定义的JWT过滤器:
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("/api/auth/login").permitAll() // 登录接口放行
.anyRequest().authenticated() // 其他请求需要认证
.and()
.addFilter(new JwtAuthenticationFilter());
}
}
总结
通过以上步骤,我们实现了一个简单的Spring Boot应用,利用JWT进行用户身份认证。用户在登录后会收到一个JWT,后续的请求需要在请求头中携带这个JWT进行身份验证。这种方式不仅简化了用户认证流程,还提高了应用的安全性。可以根据具体需求进一步扩展功能,如密码加密、黑名单策略等。