Spring Security自定义JWT过滤器实现令牌校验的完整流程

 更新时间:2026年07月07日 09:25:58   作者:知远漫谈  
Spring Security是Spring家族中的一个安全管理框架,相比另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富,这篇文章主要介绍了Spring Security自定义JWT过滤器实现令牌校验的完整流程,需要的朋友可以参考下

在现代 Web 应用开发中,身份认证与授权是保障系统安全的核心环节。随着微服务架构和前后端分离的流行,传统的基于 Session 的认证机制逐渐被无状态的 Token 认证方案所取代。其中,JWT(JSON Web Token)因其轻量、自包含、易于跨域等优势,成为主流的身份验证手段之一。

Spring Security 作为 Java 生态中最成熟、功能最强大的安全框架,提供了高度可扩展的认证与授权机制。虽然它原生支持多种认证方式(如表单登录、OAuth2、LDAP 等),但对 JWT 的支持并不直接内置,需要开发者通过自定义组件来集成。本文将深入探讨如何在 Spring Security 中实现一个自定义的 JWT 过滤器,完成完整的令牌校验流程,并确保安全性与可维护性。

💡 提示:本文假设你已具备 Spring Boot 和 Spring Security 的基础知识,了解基本的 REST API 开发流程。

什么是 JWT?

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境间安全地传递声明(claims)。它由三部分组成,以点号(.)分隔:

  1. Header(头部):包含令牌类型(通常是 JWT)和签名算法(如 HS256RS256)。
  2. Payload(载荷):包含用户信息、权限、过期时间等声明(claims)。
  3. Signature(签名):用于验证消息在传输过程中未被篡改。

一个典型的 JWT 看起来像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT 的核心优势在于无状态:服务器无需存储会话信息,只需验证签名即可信任令牌内容。这使得它非常适合分布式系统和微服务架构。

🌐 想深入了解 JWT 结构?可以访问 jwt.io,这是一个官方提供的在线解码与调试工具,支持实时查看 Header、Payload 和 Signature。

为什么需要自定义 JWT 过滤器?

Spring Security 的认证流程基于过滤器链(Filter Chain)。默认情况下,它使用 UsernamePasswordAuthenticationFilter 处理表单登录,或 BearerTokenAuthenticationFilter(在 OAuth2 资源服务器中)处理 Bearer Token。

然而,对于自定义的 JWT 实现(例如使用 HS256 算法签名、自定义用户信息结构等),Spring Security 并不提供开箱即用的支持。因此,我们需要:

  1. 拦截携带 JWT 的请求(通常在 Authorization: Bearer <token> 头部);
  2. 解析并验证 JWT 的有效性(签名、过期时间等);
  3. 将认证信息注入 Spring Security 上下文,以便后续的授权决策使用。

这就需要我们编写一个自定义的 OncePerRequestFilter,并在 Spring Security 的过滤器链中注册它。

项目结构与依赖准备 

首先,创建一个 Spring Boot 项目(推荐使用 Spring Initializr),并添加以下依赖:

<dependencies>
    <!-- Web Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <!-- JWT 支持(使用 jjwt 库) -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.5</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>

    <!-- Lombok(可选,简化代码) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

🔍 注意jjwt 是 Java 社区广泛使用的 JWT 库,由 Auth0 团队维护,文档完善且活跃。其 GitHub 仓库虽不能直接引用,但可通过 Maven Central 查看版本信息。

用户实体与 UserDetails 实现

为了与 Spring Security 集成,我们需要一个表示用户信息的实体类,并实现 UserDetails 接口。

1. 定义 User 实体

// com.example.demo.entity.User
package com.example.demo.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Long id;
    private String username;
    private String password;
    private String email;
    private String role; // 如 "ROLE_USER", "ROLE_ADMIN"
}

2. 实现 UserDetails

// com.example.demo.security.UserPrincipal
package com.example.demo.security;

import com.example.demo.entity.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.Collections;

public class UserPrincipal implements UserDetails {

    private final User user;

    public UserPrincipal(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Collections.singletonList(new SimpleGrantedAuthority(user.getRole()));
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    // 其他方法可根据业务需求返回 true/false
    @Override
    public boolean isAccountNonExpired() { return true; }
    @Override
    public boolean isAccountNonLocked() { return true; }
    @Override
    public boolean isCredentialsNonExpired() { return true; }
    @Override
    public boolean isEnabled() { return true; }

    public User getUser() {
        return user;
    }
}

UserPrincipal 封装了原始 User 对象,并实现了 Spring Security 所需的 UserDetails 接口,特别是 getAuthorities() 方法,用于返回用户的权限列表。

JWT 工具类:生成与解析令牌

接下来,我们创建一个 JwtUtil 工具类,负责 JWT 的生成、解析和验证。

// com.example.demo.security.JwtUtil
package com.example.demo.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

@Component
public class JwtUtil {

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expiration}")
    private Long expiration;

    // 从字符串生成 SecretKey(推荐使用至少 256 位的密钥)
    private SecretKey getSigningKey() {
        return Keys.hmacShaKeyFor(secret.getBytes());
    }

    // 生成 JWT
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        return createToken(claims, userDetails.getUsername());
    }

    private String createToken(Map<String, Object> claims, String subject) {
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                .signWith(getSigningKey(), SignatureAlgorithm.HS256)
                .compact();
    }

    // 从 token 中提取用户名
    public String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }

    // 通用提取方法
    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }

    // 解析并验证 token,返回 Claims
    private Claims extractAllClaims(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(getSigningKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    // 判断 token 是否过期
    public Boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }

    public Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }

    // 验证 token:检查用户名是否匹配且未过期
    public Boolean validateToken(String token, UserDetails userDetails) {
        final String username = extractUsername(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }
}

⚠️ 安全提示jwt.secret 必须是一个强密钥(建议至少 32 字节),不要硬编码在代码中。应通过配置文件或环境变量注入。

application.yml 中配置:

jwt:
  secret: your-very-strong-secret-key-32-characters-minimum
  expiration: 86400 # 24 小时,单位秒

自定义 JWT 认证过滤器

这是本文的核心部分:实现一个自定义过滤器,用于拦截请求、提取 JWT、验证并设置认证上下文。

// com.example.demo.security.JwtAuthenticationFilter
package com.example.demo.security;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

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

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;
    private final UserDetailsService userDetailsService;

    public JwtAuthenticationFilter(JwtUtil jwtUtil, UserDetailsService userDetailsService) {
        this.jwtUtil = jwtUtil;
        this.userDetailsService = userDetailsService;
    }

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

        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        // 检查 Authorization 头部是否以 "Bearer " 开头
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7); // 去掉 "Bearer "
            try {
                username = jwtUtil.extractUsername(jwt);
            } catch (Exception e) {
                logger.error("JWT 解析失败: {}", e.getMessage());
                // 不抛出异常,继续链式调用,让后续处理(如 401)
            }
        }

        // 如果能提取到用户名,且当前 SecurityContext 未认证
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            // 验证 token 有效性
            if (jwtUtil.validateToken(jwt, userDetails)) {
                // 创建认证对象
                UsernamePasswordAuthenticationToken authenticationToken =
                        new UsernamePasswordAuthenticationToken(
                                userDetails, null, userDetails.getAuthorities());
                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                // 设置到 SecurityContext
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }

        // 继续过滤器链
        filterChain.doFilter(request, response);
    }
}

关键点解析:

  1. OncePerRequestFilter:确保每个请求只执行一次过滤逻辑,避免重复处理。
  2. 提取 Token:从 Authorization 头部提取 Bearer Token。
  3. 验证 Token:使用 JwtUtil 验证签名和过期时间。
  4. 设置认证上下文:如果验证通过,创建 UsernamePasswordAuthenticationToken 并放入 SecurityContextHolder,这样后续的控制器或方法级安全注解(如 @PreAuthorize)就能获取到当前用户信息。
  5. 异常处理:捕获 JWT 解析异常(如签名无效、格式错误),但不中断过滤器链,而是让请求继续,最终由 Spring Security 返回 401。

实现 UserDetailsService

为了让 JwtAuthenticationFilter 能加载用户信息,我们需要实现 UserDetailsService

// com.example.demo.service.CustomUserDetailsService
package com.example.demo.service;

import com.example.demo.entity.User;
import com.example.demo.security.UserPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class CustomUserDetailsService implements UserDetailsService {

    // 模拟数据库(实际项目中应查询数据库)
    private static final Map<String, User> USER_DB = new HashMap<>();

    static {
        USER_DB.put("alice", new User(1L, "alice", "password", "alice@example.com", "ROLE_USER"));
        USER_DB.put("admin", new User(2L, "admin", "admin123", "admin@example.com", "ROLE_ADMIN"));
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = USER_DB.get(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在: " + username);
        }
        return new UserPrincipal(user);
    }
}

🧩 在真实项目中,USER_DB 应替换为对数据库(如 JPA Repository)的查询。

配置 Spring Security

现在,我们将自定义的 JWT 过滤器集成到 Spring Security 的过滤器链中。

// com.example.demo.config.SecurityConfig
package com.example.demo.config;

import com.example.demo.security.JwtAuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable() // JWT 无状态,禁用 CSRF
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无会话
            .and()
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/auth/**").permitAll() // 登录接口放行
                .requestMatchers("/public/**").permitAll() // 公共接口
                .anyRequest().authenticated() // 其他请求需认证
            )
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }
}

配置说明:

  • csrf().disable():由于 JWT 是无状态的,CSRF 攻击不适用,可禁用。
  • SessionCreationPolicy.STATELESS:明确告知 Spring Security 不创建 HTTP 会话。
  • addFilterBefore:将 JwtAuthenticationFilter 插入到 UsernamePasswordAuthenticationFilter 之前,确保在表单登录处理前先尝试 JWT 认证。
  • 路径放行/auth/** 用于登录接口,不应受 JWT 保护。

登录接口与 Token 分发

用户需要先通过用户名/密码登录,获取 JWT。

// com.example.demo.controller.AuthController
package com.example.demo.controller;

import com.example.demo.entity.User;
import com.example.demo.security.JwtUtil;
import com.example.demo.service.CustomUserDetailsService;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AuthController {

    private final AuthenticationManager authenticationManager;
    private final CustomUserDetailsService userDetailsService;
    private final JwtUtil jwtUtil;

    public AuthController(AuthenticationManager authenticationManager,
                          CustomUserDetailsService userDetailsService,
                          JwtUtil jwtUtil) {
        this.authenticationManager = authenticationManager;
        this.userDetailsService = userDetailsService;
        this.jwtUtil = jwtUtil;
    }

    @PostMapping("/auth/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
        try {
            // 触发 Spring Security 的认证流程
            authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                    loginRequest.getUsername(),
                    loginRequest.getPassword()
                )
            );
        } catch (BadCredentialsException e) {
            return ResponseEntity.status(401).body("用户名或密码错误");
        }

        // 认证成功,生成 JWT
        final UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
        final String jwt = jwtUtil.generateToken(userDetails);

        return ResponseEntity.ok(new JwtResponse(jwt));
    }

    public static class LoginRequest {
        private String username;
        private String password;
        // getters and setters
        public String getUsername() { return username; }
        public void setUsername(String username) { this.username = username; }
        public String getPassword() { return password; }
        public void setPassword(String password) { this.password = password; }
    }

    public static class JwtResponse {
        private String token;
        public JwtResponse(String token) { this.token = token; }
        public String getToken() { return token; }
    }
}

流程说明

  1. 客户端发送用户名/密码到 /auth/login
  2. 使用 AuthenticationManager 进行认证(底层调用 UserDetailsService 和密码编码器);
  3. 认证成功后,调用 JwtUtil.generateToken() 生成 JWT;
  4. 返回 {"token": "xxx"}

测试受保护的 API

创建一个简单的受保护接口:

// com.example.demo.controller.ProfileController
package com.example.demo.controller;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProfileController {

    @GetMapping("/api/profile")
    public String profile(@AuthenticationPrincipal UserDetails userDetails) {
        return "Hello, " + userDetails.getUsername() + "! Your role: " + 
               userDetails.getAuthorities();
    }
}

测试步骤:

  1. 登录获取 Token

    curl -X POST http://localhost:8080/auth/login \
         -H "Content-Type: application/json" \
         -d '{"username":"alice","password":"password"}'
    

    响应:

    {"token":"eyJhbGciOiJIUzI1NiJ9..."}
  2. 使用 Token 访问受保护资源

    curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
         http://localhost:8080/api/profile
    

    响应:

    Hello, alice! Your role: [ROLE_USER]
    
  3. 无效 Token 测试

    • 修改 Token 任意字符 → 返回 401
    • 使用过期 Token → 返回 401
    • 不带 Token → 返回 401

安全增强建议

虽然上述实现已满足基本需求,但在生产环境中还需考虑以下安全措施:

1. 使用强密钥

确保 jwt.secret高熵随机字符串(至少 32 字节)。可使用以下命令生成:

openssl rand -base64 32

2. 添加 Token 黑名单(可选)

JWT 一旦签发,在过期前始终有效。若需支持“立即注销”,可引入 Redis 存储已注销的 Token 及其过期时间,在验证时检查黑名单。

3. 防止重放攻击

可在 JWT Payload 中加入 jti(JWT ID)和 iat(签发时间),并在服务端记录最近使用的 jti,拒绝重复使用。

4. HTTPS 强制启用

JWT 通过 HTTP 头部传输,必须使用 HTTPS 防止中间人窃取。

5. 限制 Token 有效期

短期 Token(如 15-30 分钟)配合 Refresh Token 机制更安全。本文未实现 Refresh Token,但可参考 Auth0 的最佳实践

整体认证流程图

让我们用 Mermaid 图表直观展示整个 JWT 认证流程:

该图清晰展示了从登录到访问受保护资源的完整流程,以及各组件之间的协作关系。

常见问题与排查

Q1: 为什么过滤器没有生效?

  • 检查是否在 SecurityConfig 中正确调用了 addFilterBefore
  • 确保 JwtAuthenticationFilter 被 Spring 扫描到(有 @Component 注解);
  • 查看日志,确认过滤器是否被调用。

Q2: Token 验证总是失败?

  • 检查 jwt.secret 是否一致(生成和验证使用同一密钥);
  • 确认 Token 是否过期;
  • 使用 jwt.io 解码 Token,检查 Payload 内容是否符合预期。

Q3: 如何支持多角色授权?

UserPrincipal.getAuthorities() 中返回多个 GrantedAuthority,例如:

Arrays.asList(
    new SimpleGrantedAuthority("ROLE_USER"),
    new SimpleGrantedAuthority("SCOPE_READ")
);

然后在控制器使用:

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin")
public String adminOnly() { ... }

Q4: 能否在 JWT 中存储更多信息?

可以!在 JwtUtil.createToken()claims 中添加自定义字段:

claims.put("userId", user.getId());
claims.put("email", user.getEmail());

解析时通过 extractClaim(token, claims -> claims.get("userId", Long.class)) 获取。

性能考量

  • JWT 解析开销:每次请求都要解析和验证 JWT,但 jjwt 库性能良好,通常不是瓶颈。
  • 避免频繁数据库查询:在 JwtAuthenticationFilter 中,每次请求都会调用 UserDetailsService.loadUserByUsername()。若用户信息不常变,可考虑缓存(如 Caffeine 或 Redis)。
  • 无状态优势:省去了 Session 存储和集群同步的开销,适合高并发场景。

扩展:Refresh Token 机制

虽然本文聚焦于基础 JWT 实现,但实际应用中常需 Refresh Token 来延长会话。其基本思路是:

  1. 登录时返回两个 Token:access_token(短有效期)和 refresh_token(长有效期);
  2. access_token 过期后,客户端用 refresh_token 请求新的 access_token
  3. refresh_token 应存储在服务端(如数据库),支持撤销。

📚 想了解 Refresh Token 的详细实现?推荐阅读 OAuth 2.0 RFC 6749 中的相关章节。

总结

通过本文,我们完整实现了一个基于 Spring Security 的自定义 JWT 认证方案。关键步骤包括:

  1. 理解 JWT 原理及其在无状态认证中的优势;
  2. 实现 UserDetailsUserDetailsService,桥接业务用户与 Spring Security;
  3. 编写 JwtUtil,封装 JWT 的生成与验证逻辑;
  4. 创建 JwtAuthenticationFilter,在请求进入时自动完成认证;
  5. 配置 Spring Security,禁用 Session、CSRF,并注册自定义过滤器;
  6. 提供登录接口,分发 JWT;
  7. 保护 API 资源,利用 Spring Security 的授权机制。

这套方案结构清晰、扩展性强,适用于大多数中小型 Web 应用。当然,安全是一个持续演进的过程,开发者应根据实际需求不断加固系统。

🌟 最后提醒:永远不要在 JWT 中存储敏感信息(如密码、身份证号),因为 Payload 是 Base64 编码,可被轻易解码!

到此这篇关于Spring Security自定义JWT过滤器实现令牌校验的文章就介绍到这了,更多相关Spring Security实现令牌校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring框架开发IOC两种创建工厂方法详解

    Spring框架开发IOC两种创建工厂方法详解

    这篇文章主要介绍了Spring框架IOC两种创建工厂方法详解,文中附含详细的代码示例分别对静态方法和实例方法创建工厂作了简要的分析
    2021-09-09
  • hibernate-validator后端表单数据校验的使用示例详解

    hibernate-validator后端表单数据校验的使用示例详解

    这篇文章主要介绍了hibernate-validator后端表单数据校验的使用,hibernate-validator提供的校验方式为在类的属性上加入相应的注解来达到校验的目的,本文结合示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • 实例总结Java多线程编程的方法

    实例总结Java多线程编程的方法

    在本篇文章里我们给大家总结了Java多线程编程的方法以及相关实例代码,需要的朋友们可以学习下。
    2018-10-10
  • SpringBoot配置Redis连接池的实现步骤

    SpringBoot配置Redis连接池的实现步骤

    本文主要介绍了SpringBoot配置Redis连接池的实现步骤,详细的讲解了连接池的作用、配置方式、连接池参数说明,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • MyBatis foreach 批量更新实例

    MyBatis foreach 批量更新实例

    这篇文章主要介绍了MyBatis foreach 批量更新实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • 基于ClasspathResource路径问题的解决

    基于ClasspathResource路径问题的解决

    这篇文章主要介绍了ClasspathResource路径问题的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java9版本新特性同一个Jar支持多JDK版本运行

    Java9版本新特性同一个Jar支持多JDK版本运行

    这篇文章主要为大家介绍了Java9新版本的特性之同一个Jar支持多JDK版本运行的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • 教你在JNA中将本地方法映射到JAVA代码中的示例

    教你在JNA中将本地方法映射到JAVA代码中的示例

    对于JNI来说,我们可以使用native关键字来定义本地方法。那么在JNA中有那些在JAVA代码中定义本地方法的方式呢?对JNA本地方法映射JAVA代码的相关知识感兴趣的朋友一起看看吧
    2022-04-04
  • Java详细讲解IO流的Writer与Reader操作

    Java详细讲解IO流的Writer与Reader操作

    Writer与Reader类不能直接调用,需要使用多带的方法调用它们的子类,在他们的前边加上一个File即可如(FileWriter或FileReader)的多态方法进行其调用,并且他们也是抽象类调用需要连接接口Exception,它们的优点在于可以直接写入或读出内容,不需要使用byte转八进制
    2022-05-05
  • ShardingSphere JDBC强制路由使用的项目实践

    ShardingSphere JDBC强制路由使用的项目实践

    在某些特定场景下,可能需要绕过分片规则直接定位到特定的数据库或表,这种情况下就可以使用HintRouting,本文就来介绍一下ShardingSphere JDBC强制路由使用的项目实践,感兴趣的可以了解一下
    2024-06-06

最新评论