当前位置: 首页 > article >正文

使用 Spring Security 和 JWT 实现安全认证机制

在现代 Web 应用中,安全认证和授权是保障数据安全和用户隐私的核心机制。Spring Security 是 Spring 框架下专为安全设计的模块,具有高度的可配置性和扩展性。而 JWT(JSON Web Token) 则是当前流行的认证解决方案,因其无状态、可扩展性强等特点被广泛应用于微服务和移动应用中。

本文将从以下几个部分详细介绍如何使用 Spring Security 和 JWT 实现一个完整的认证机制:

  1. JWT 认证流程概述
  2. Spring Security 的基本配置
  3. JWT 生成与解析
  4. 基于 Spring Security 的 JWT 安全配置
  5. 实现用户登录和认证

1. JWT 认证流程概述

JWT 的认证流程如下:

  • 用户登录:用户通过用户名和密码发送请求给服务器。
  • 服务器验证:服务器验证用户身份,验证通过后生成 JWT Token。
  • Token 下发:服务器将生成的 Token 返回给客户端。
  • 后续请求携带 Token:客户端在后续请求中将 JWT Token 添加到请求头中,服务器通过解析和验证 Token 确认请求的合法性。

这种方式的核心优势在于 Token 是无状态的,服务器无需维护用户的会话信息,且 JWT 可在分布式系统中实现共享认证。

2. Spring Security 的基本配置

创建一个简单的 Spring Boot 项目,并添加 Spring Security 和 JWT 的依赖:

<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>
配置 SecurityConfig 类

创建 SecurityConfig 类以配置 Spring Security 基本设置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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();
    }
}

上面的配置指定 /login 接口公开访问,其余接口需要认证后才能访问。

3. JWT 生成与解析

使用 JWT 库生成和解析 Token。创建 JwtUtil 工具类,实现生成和验证 JWT 的方法:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JwtUtil {

    private static final String SECRET_KEY = "mySecretKey";

    // 生成 JWT
    public static String generateToken(String username) {
        return Jwts.builder()
                   .setSubject(username)
                   .setIssuedAt(new Date())
                   .setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 24小时有效期
                   .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                   .compact();
    }

    // 解析 JWT
    public static Claims parseToken(String token) {
        return Jwts.parser()
                   .setSigningKey(SECRET_KEY)
                   .parseClaimsJws(token)
                   .getBody();
    }
}

4. 基于 Spring Security 的 JWT 安全配置

在 Spring Security 过滤链中添加 JWT 过滤器。实现一个 JwtAuthenticationFilter 类,在每次请求时拦截并验证 Token:

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import io.jsonwebtoken.Claims;

public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

    public JwtAuthenticationFilter(AuthenticationManager authManager) {
        super(authManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        String token = request.getHeader("Authorization");
        if (token == null || !token.startsWith("Bearer ")) {
            chain.doFilter(request, response);
            return;
        }

        Claims claims = JwtUtil.parseToken(token.replace("Bearer ", ""));
        String username = claims.getSubject();

        if (username != null) {
            UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
            SecurityContextHolder.getContext().setAuthentication(auth);
        }
        chain.doFilter(request, response);
    }
}

JwtAuthenticationFilter 过滤器添加到 SecurityConfig 中:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .authorizeRequests()
        .antMatchers("/login").permitAll()
        .anyRequest().authenticated()
        .and()
        .addFilter(new JwtAuthenticationFilter(authenticationManager()));
}

5. 实现用户登录和认证

创建一个登录控制器 AuthController,验证用户后生成 JWT:

import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;

@RestController
public class AuthController {

    @PostMapping("/login")
    public void login(@RequestParam String username, @RequestParam String password, HttpServletResponse response) {
        // 这里简单校验用户名密码
        if ("user".equals(username) && "password".equals(password)) {
            String token = JwtUtil.generateToken(username);
            response.setHeader("Authorization", "Bearer " + token);
        } else {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }
}

以上代码实现了一个简单的登录接口,用户登录成功后将返回 JWT Token,并将该 Token 存储在响应头中。

6. 测试与验证

  1. 获取 Token:使用客户端(例如 Postman)请求 /login 接口,得到包含 JWT Token 的响应头。
  2. 访问受保护接口:将 Token 添加到请求头 Authorization 中,再次请求受保护接口,验证是否可以成功访问。

结论

通过以上步骤,我们实现了一个基于 Spring Security 和 JWT 的安全认证系统。在实际项目中,可以进一步扩展此功能,例如集成数据库实现用户管理、配置 JWT 自动续签等。这种基于 JWT 的无状态认证适用于分布式系统和微服务架构,有助于提高系统的安全性和可扩展性。


http://www.kler.cn/a/383688.html

相关文章:

  • RC高通滤波器Bode图分析(传递函数零极点)
  • 这款神器,运维绝杀 !!!
  • 【GPT使用技巧】用AI出一门课
  • 【开发工具】Git
  • 【git】github Actions的作用
  • Docker配置国内源加速
  • MySQL记录锁、间隙锁、临键锁(Next-Key Locks)详解
  • PostgreSQL (八) 创建分区
  • 如何选择适合CMS运行的服务器?
  • MySQL 8.0在windows环境安装及配置
  • STM32项目---水质水位检测
  • nuPlan最新SOTA,香港科技大学发布基于学习决策范围内的规划PlanScope
  • Java 网络编程(一)—— UDP数据报套接字编程
  • mysql数据同步到sql server
  • SpringBoot在线教育系统:云部署策略
  • 4.3 Linux的中断处理流程
  • 网络安全:数字时代的防护盾
  • Linux系统编程学习 NO.10——进程的概念(1)
  • Linux,shell基础,变量,数值运算
  • 矩阵论 •「线性变换」
  • Linux系列-进程的状态
  • 动态规划理论基础和习题【力扣】【算法学习day.25】
  • apache poi 实现下拉框联动校验
  • MySQL表转移数据的三种方式
  • 【Python进阶】Python中的网络爬虫策略:高效数据抓取与解析
  • 数据库优化指南:如何将基本功能运用到极致?