我使用 Spring Boot 作为资源服务器,并使用 Keycloak 进行身份验证和授权。我的设置包括用于处理 JWT 令牌的 spring-oauth2-resource-server 和用于端点访问控制的 keycloak-policy-enforcer。这是所需的行为:
但是,在我当前的设置下,没有令牌的请求会到达策略执行器,策略执行器会响应 403 而不是 401。
这是我的 Spring Security 配置:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable);
http.cors(Customizer.withDefaults());
http.anonymous(AbstractHttpConfigurer::disable);
http.oauth2ResourceServer(t -> t.jwt(Customizer.withDefaults()));
http.sessionManagement(t -> t.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.authorizeHttpRequests(httpMatcher -> httpMatcher.requestMatchers(whiteList).permitAll().anyRequest().authenticated());
http.exceptionHandling((exceptions) -> exceptions.authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint()).accessDeniedHandler(new BearerTokenAccessDeniedHandler()));
http.addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter.class);
return http.build();
}
private ServletPolicyEnforcerFilter createPolicyEnforcerFilter() {
return new ServletPolicyEnforcerFilter(new ConfigurationResolver() {
@Override
public PolicyEnforcerConfig resolve(HttpRequest request) {
try {
PolicyEnforcerConfig config = JsonSerialization.readValue(getClass().getResourceAsStream("/policy-enforcer.json"), PolicyEnforcerConfig.class);
config.setAuthServerUrl(serverUrl);
config.setRealm(realM);
config.setResource(clientId);
config.setCredentials(Map.of("secret", clientSecret));
return config;
} catch (IOException e) {
System.out.println(e.getMessage());
throw new RuntimeException(e);
}
}
});
}
我尝试过的 我已尝试调整过滤器顺序,但仍然看到没有令牌的请求的 403 响应。有人对如何确保没有令牌的请求在到达策略执行者之前返回 401 有建议吗?
预先感谢您的任何见解!
看来您的问题主要与春季安全过滤器订单有关。 我创建了一个示例存储库,展示了如何使用 Keycloak 保护应用程序并调用它,您可以在here查看。
与您的具体过滤器问题相关,您可以通过检查我的配置方式来了解如何确保顺序合适此处。主要部分是确保过滤器添加在
AuthorizationFilter
之前。 Spring Security 文档中有更详细的解释。
在您的情况下,您正在过滤器内执行策略。在这种情况下,您需要按照
文档中的指定抛出
AccessDeniedException
(对于 403)或 AuthenticationException
(对于 401)。
Spring Security 非常庞大,有时很难找到东西,但如果您搜索足够长的时间或只是阅读全部内容,那么它们都可以在文档中找到。但希望这能解释您正在寻找的内容。