Springboot整合JWT实现Token验证

琉璃若梦 2023-03-27 ⋅ 20 阅读

介绍

在当今的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来自动生成项目结构。

  1. 打开Spring Initializr的网站(https://start.spring.io/)。
  2. 在该网站上,我们可以选择项目的一些基本配置,例如项目的坐标、依赖等。我们需要选择以下配置:
    • Project:Maven Project
    • Language:Java
    • Spring Boot:2.x.x
    • Group:com.example
    • Artifact:jwt-demo
    • Dependencies:选择Web和Security。
  3. 点击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来测试我们的接口。

  1. 首先,启动我们的Spring Boot应用程序。
  2. 使用Postman发送登录请求,例如POST http://localhost:8080/login,请求体为:
{
  "username": "admin",
  "password": "password"
}
  1. 如果用户名和密码正确,我们将从响应中获取到JWT令牌。
  2. 然后,我们可以使用该令牌来访问需要权限验证的接口,例如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


全部评论: 0

    我有话说: