介绍
在当今的Web应用程序中,身份验证和授权是非常重要的一部分。JSON Web Token(JWT)是一种安全且可扩展的身份验证方法,它通过在用户登录后生成一个加密的令牌,然后将该令牌发送给客户端,客户端在后续的请求中使用该令牌来验证其身份和权限。这种方式与传统的基于会话的身份验证方式相比具有很多优势,例如无状态、可扩展等。
Spring Boot是一个用于开发独立的、产品级的Spring应用程序的框架。它提供了快速、方便的方式来搭建Spring应用程序,并集成了许多常用的功能和组件。
本文将介绍如何在Spring Boot应用程序中整合JWT实现Token验证。
准备工作
在开始之前,我们需要确保已经安装了以下相关软件:
- JDK(Java Development Kit)
- Maven(项目构建工具)
- IDE(Eclipse、IntelliJ IDEA等)
- Postman(用于测试API)
创建Spring Boot项目
首先,我们需要创建一个基本的Spring Boot项目。可以通过使用Spring Initializr来自动生成项目结构。
- 打开Spring Initializr的网站(https://start.spring.io/)。
- 在该网站上,我们可以选择项目的一些基本配置,例如项目的坐标、依赖等。我们需要选择以下配置:
- Project:Maven Project
- Language:Java
- Spring Boot:2.x.x
- Group:com.example
- Artifact:jwt-demo
- Dependencies:选择Web和Security。
- 点击Generate按钮,下载并解压生成的项目文件。
集成JWT
接下来,我们需要将JWT集成到我们的Spring Boot应用程序中。可以通过在pom.xml文件中添加以下依赖项来实现:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
这将添加一个与JWT相关的依赖库。
接下来,我们需要编写一个JWT工具类来实现JWT的生成和解析。
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtils {
private static final String SECRET = "secretKey";
private static final long EXPIRATION_TIME = 864000000; // 10 days
public static String generateToken(String username) {
Map<String, Object> claims = new HashMap<>();
claims.put("sub", username);
claims.put("created", new Date());
return Jwts.builder()
.setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
public static String getUsernameFromToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
public static boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
}
上述工具类包含了生成令牌、从令牌中获取用户名以及验证令牌的方法。
现在,我们可以在我们的Spring Boot应用程序中使用这些方法来生成和验证JWT令牌。例如,在登录接口中生成JWT令牌:
@RestController
public class LoginController {
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody LoginForm loginForm) {
// 验证用户名和密码
if (!loginForm.getUsername().equals("admin") || !loginForm.getPassword().equals("password")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid username or password");
}
// 生成JWT令牌
String token = JwtUtils.generateToken(loginForm.getUsername());
return ResponseEntity.ok(token);
}
}
现在,当我们调用登录接口时,将会生成一个JWT令牌并返回给客户端。
Token验证
下面,我们需要在接口中验证JWT令牌的有效性。可以使用Spring Security来实现这个功能。
首先,我们需要添加Spring Security的依赖项到pom.xml文件中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
然后,我们需要创建一个自定义的JwtAuthenticationFilter
来处理JWT令牌的验证逻辑。
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final String SECRET = "secretKey";
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
String path = request.getServletPath();
return !path.equals("/login");
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String header = request.getHeader("Authorization");
if (StringUtils.hasText(header) && header.startsWith("Bearer ")) {
String token = header.substring(7);
if (JwtUtils.validateToken(token)) {
String username = JwtUtils.getUsernameFromToken(token);
User principal = new User(username, "", Collections.emptyList());
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(principal, null, Collections.emptyList());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
}
在上述代码中,我们通过从请求头中获取令牌,并使用工具类验证令牌的有效性。如果令牌有效,将会获取用户名,并设置认证信息到Spring Security的上下文中。
最后,我们需要在应用程序的配置类中配置上面的过滤器:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated();
}
}
上述配置类中,我们禁用了跨站请求伪造(CSRF)保护,并添加了自定义的JWT验证过滤器。
测试
现在,我们已经完成了Spring Boot整合JWT实现Token验证的配置。我们可以使用Postman来测试我们的接口。
- 首先,启动我们的Spring Boot应用程序。
- 使用Postman发送登录请求,例如
POST http://localhost:8080/login
,请求体为:
{
"username": "admin",
"password": "password"
}
- 如果用户名和密码正确,我们将从响应中获取到JWT令牌。
- 然后,我们可以使用该令牌来访问需要权限验证的接口,例如
GET http://localhost:8080/api/user
,请求头中添加Authorization: Bearer <token>
。
结论
通过本文,我们学习了如何使用Spring Boot整合JWT实现Token验证。JWT提供了一种安全且可扩展的身份验证方式,并且与Spring Boot框架完美集成。通过实现自定义的JWT工具类和Spring Security过滤器,我们可以轻松地实现JWT的生成和验证功能。这种方式消除了对基于会话的身份验证的依赖,使得我们的应用程序更加简单和可扩展。
完整代码示例可以在GitHub上找到:https://github.com/example/jwt-demo。
本文来自极简博客,作者:琉璃若梦,转载请注明原文链接:Springboot整合JWT实现Token验证