You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring资源服务器中解析自定义JWT并通过Redis验证权限

解决方案

1. 配置资源服务器解析自定义JWT字段

首先让Spring资源服务器能够解析JWT中的自定义authority字段,提取用户角色:

@Configuration
@EnableResourceServer
public class ResourceServerConfig {

    @Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
    private String jwkSetUri;

    @Bean
    public JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();
    }

    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(jwt -> {
            List<Map<String, String>> authorities = jwt.getClaim("authority");
            if (authorities == null || authorities.isEmpty()) {
                return Collections.emptyList();
            }
            return authorities.stream()
                    .map(auth -> new SimpleGrantedAuthority(auth.get("role")))
                    .collect(Collectors.toList());
        });
        return converter;
    }
}

2. 实现Redis权限/限制校验组件

创建组件负责从Redis获取用户权限与限制数据,并完成校验逻辑:

@Component
public class RedisPermissionValidator {

    private final StringRedisTemplate stringRedisTemplate;

    public RedisPermissionValidator(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public boolean validate(String username) {
        List<String> permissionRestrictions = stringRedisTemplate.opsForList().range(username, 0, -1);
        if (permissionRestrictions == null || permissionRestrictions.isEmpty()) {
            return false;
        }
        // 优先检查是否存在限制项,存在则直接拒绝
        boolean hasRestriction = permissionRestrictions.stream().anyMatch(item -> item.startsWith("Restriction"));
        if (hasRestriction) {
            return false;
        }
        // 检查是否存在有效权限项
        return permissionRestrictions.stream().anyMatch(item -> item.startsWith("Permission"));
    }
}

3. 自定义请求过滤器实现实时校验

添加自定义过滤器,在JWT认证完成后,提取用户信息并调用Redis校验组件,不符合条件则返回401:

@Component
public class RedisAuthorizationFilter extends OncePerRequestFilter {

    private final RedisPermissionValidator permissionValidator;
    private final JwtDecoder jwtDecoder;

    public RedisAuthorizationFilter(RedisPermissionValidator permissionValidator, JwtDecoder jwtDecoder) {
        this.permissionValidator = permissionValidator;
        this.jwtDecoder = jwtDecoder;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            String token = authorizationHeader.substring(7);
            try {
                Jwt jwt = jwtDecoder.decode(token);
                String username = jwt.getSubject();
                boolean isValid = permissionValidator.validate(username);
                if (!isValid) {
                    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                    response.getWriter().write("401 unauthorized");
                    return;
                }
            } catch (JwtException e) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.getWriter().write("Invalid JWT token");
                return;
            }
        }
        filterChain.doFilter(request, response);
    }
}

4. 配置安全过滤链整合自定义过滤器

将自定义过滤器加入Spring Security过滤链,确保在JWT认证后执行校验:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final RedisAuthorizationFilter redisAuthorizationFilter;
    private final JwtAuthenticationConverter jwtAuthenticationConverter;
    private final JwtDecoder jwtDecoder;

    public SecurityConfig(RedisAuthorizationFilter redisAuthorizationFilter, JwtAuthenticationConverter jwtAuthenticationConverter, JwtDecoder jwtDecoder) {
        this.redisAuthorizationFilter = redisAuthorizationFilter;
        this.jwtAuthenticationConverter = jwtAuthenticationConverter;
        this.jwtDecoder = jwtDecoder;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth
                        .anyRequest().authenticated()
                )
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt
                                .decoder(jwtDecoder)
                                .jwtAuthenticationConverter(jwtAuthenticationConverter)
                        )
                )
                .addFilterAfter(redisAuthorizationFilter, BearerTokenAuthenticationFilter.class);
        return http.build();
    }
}

关键说明

  • JWT解析:通过JwtAuthenticationConverter自定义提取authority字段中的角色,让Spring Security能识别用户身份角色。
  • Redis校验逻辑:优先检查限制项,存在则直接拒绝请求;无限制时再校验是否存在有效权限,确保请求合法性。
  • 过滤器顺序:将自定义过滤器放在BearerTokenAuthenticationFilter之后,保证JWT完成认证后再执行Redis校验。

内容的提问来源于stack exchange,提问作者Vinayak Pattar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 12:40:25