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

基于自定义HTTP Header的Spring Security权限过滤实现疑问

Spring Security RBAC实现问题及JWT替代疑问

问题描述

我正尝试用Spring Security实现RBAC(基于角色的访问控制)。用户认证已经单独实现,系统会生成sessionId供应用使用。我希望Spring Security从HTTP Header中获取sessionId,再通过这个sessionId从数据库获取权限信息,以此判断用户是否有权访问特定端点。当前问题是:我不知道如何按需从数据库获取权限,也不确定现有配置是否正确。

现有实现代码

CustomSecurityFilter配置类

@Configuration
@EnableWebSecurity
public class CustomSecurityFilter {

  @Bean
  AuthenticationManager customAuthenticationManager(HttpHeaderAuthenticationProvider httpHeaderAuthenticationProvider) {
    return new ProviderManager(List.of(httpHeaderAuthenticationProvider));
  }

  @Bean
  HttpHeaderAuthenticationProvider newHttpHeaderAuthenticationProvider() {
    return new HttpHeaderAuthenticationProvider();
  }

  @Bean
  public SecurityFilterChain filterChain(HttpSecurity http,
      AuthenticationManager authenticationManager) throws Exception {
    http.addFilterBefore(getFilter(authenticationManager), AnonymousAuthenticationFilter.class)
        .authorizeRequests()
        .antMatchers(HttpMethod.GET, "/api/apples").hasAuthority("viewApples")
        .antMatchers(HttpMethod.POST, "/api/apples").hasAuthority("createApples");
    return http.build();
  }

  private Filter getFilter(AuthenticationManager authenticationManager) {
    return new HttpHeaderProcessingFilter(
        new OrRequestMatcher(
            new AntPathRequestMatcher("/api/apples/**")
        ),
        authenticationManager
    );
  }
}

HttpHeaderAuthenticationProvider类

public class HttpHeaderAuthenticationProvider implements AuthenticationProvider {
  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    var sessionId = ((String) authentication.getPrincipal());

    // 不知道怎么连接数据库获取session和权限信息?
    boolean isValid = sessionId != null;
    if (isValid) {
      return newPreAuthenticatedToken("sessionId", List.of());
    } else {
      throw new AccessDeniedException("Invalid sessionId");
    }
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return PreAuthenticatedAuthenticationToken.class.equals(authentication);
  }

  public static PreAuthenticatedAuthenticationToken newPreAuthenticatedToken(String userId, List<String> permissions) {
    var grantedAuthorityList = new ArrayList<GrantedAuthority>();
    for (String permission : permissions) {
      grantedAuthorityList.add(new SimpleGrantedAuthority(permission));
    }

    return new PreAuthenticatedAuthenticationToken(userId, null, grantedAuthorityList);
  }
}

HttpHeaderProcessingFilter类

public class HttpHeaderProcessingFilter extends AbstractAuthenticationProcessingFilter {

  public HttpHeaderProcessingFilter(RequestMatcher requiresAuthenticationRequestMatcher,
                                    AuthenticationManager authenticationManager) {
    super(requiresAuthenticationRequestMatcher);
    setAuthenticationManager(authenticationManager);
  }

  @Override
  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
      throws AuthenticationException {
    return getAuthenticationManager().authenticate(
        // 不确定这么做是否正确
        HttpHeaderAuthenticationProvider.newPreAuthenticatedToken("sessionId", List.of())
    );
  }

  @Override
  protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                          Authentication authResult) throws IOException, ServletException {
    SecurityContextHolder.getContext().setAuthentication(authResult);
    chain.doFilter(request, response);
  }
}

额外疑问

另外我还想了解,用JWT替代自定义sessionId来实现RBAC+会话处理是否合适?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 04:36:18