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有帮助!

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部