java Spring Security配置不允许公共访问特定端点

kmb7vmvb  于 2023-06-20  发布在  Java
关注(0)|答案(1)|浏览(124)

正如标题所述,我面临着允许访问我的微服务架构中应该公开访问的端点的问题。我正在使用Keycloak进行基于角色的身份验证,它工作得很好,除了在访问公共端点时,我一直遇到401 Unauthorized错误,尽管在我的SecurityFilterChain Bean中使用了.permitAll()方法。
需要注意的是,我还使用Spring Clouds API网关将传入请求路由到负载平衡的微服务。
代码和配置类粘贴在下面,但这是我过去几天一直在尝试解决问题的方法。
1.我最初在API网关级别实现了身份验证。然而,无论我尝试什么,当从我的微服务访问端点时,我总是得到401状态,这导致了解决方案尝试2。
1.我在微服务级别实现了身份验证,基于角色的身份验证工作正常,但访问公共端点仍然是一个问题。
1.我尝试在我的微服务SecurityFilterChain Bean中禁用CSRF,但它也没有改变任何东西。
1.目前,我完全删除了微服务中SecurityFilterChain Bean的公共端点。相反,我在SecurityWebFilterChainBean中的API网关级别添加了公共端点,这也不起作用。
1.作为最后的手段,我将javax.annotation.security包中的PermitAll注解添加到我的PublicUserController(所有公共可用端点的控制器类)中的端点,但这不起作用。
除了教程,这是我第一次自己实现这样的东西,所以它仍然是相当新的,我不知道从哪里开始。如能就这一问题提供任何正确方向的指导,将不胜感激。如果需要的话,我很乐意澄清任何事情或添加任何额外的代码。任何帮助/指导都非常感谢。

用户服务

安全配置
    • 注意:**我尝试公开的路径是/public/users/**。它应该接受HttpMethod.PUT、HttpMethod.DELETE和HttpMethod.POST。
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfiguration {

    private final AuthenticationConverter authenticationConverter;

    @Autowired
    public SecurityConfiguration(AuthenticationConverter authenticationConverter) {
        this.authenticationConverter = authenticationConverter;
    }

    @Bean
    public SecurityFilterChain securedSecurityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(request -> request
                        .requestMatchers("/public/users/**").permitAll()
                        .requestMatchers("/admins/users/**").hasRole("ADMIN")
                        .requestMatchers("/subscribers/users/**").hasRole("SUBSCRIBER")
                        .anyRequest().authenticated())
                .oauth2ResourceServer()
                .jwt()
                .jwtAuthenticationConverter(authenticationConverter);

        return http.build();
    }
}

Api网关

UserServiceRouteConfiguration
@Configuration
public class UserServiceRouteConfiguration {

    private final String API_VERSION = "v0.1-dev";

    @Bean
    public RouteLocator userServiceRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("user-service", route -> route
                        .path("/user-service/" + API_VERSION + "/subscribers/users/**")
                        .and().method(HttpMethod.GET, HttpMethod.PUT, HttpMethod.POST, HttpMethod.DELETE)
                        .uri("lb://user-service"))
                .route("user-service", route -> route
                        .path("/user-service/" + API_VERSION + "/admins/users/**")
                        .and().method(HttpMethod.GET, HttpMethod.PUT, HttpMethod.POST, HttpMethod.DELETE)
                        .uri("lb://user-service"))
                .route("user-service", route -> route
                        .path("/user-service/" + API_VERSION + "/public/users/**")
                        .and().method(HttpMethod.GET, HttpMethod.PUT, HttpMethod.POST, HttpMethod.DELETE)
                        .uri("lb://user-service"))
                .build();
    }
}
安全配置
    • 注意:**这是我第一次开始实现基于角色的身份验证的地方,但并没有像上面提到的那样工作。
@Configuration
@EnableWebFluxSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity security) {
        return security.csrf().disable()
                .authorizeExchange(exchange -> exchange
                        .pathMatchers("/eureka/**").permitAll()
                        .anyExchange().authenticated())
                .oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt)
                .build();
    }
}
mspsb9vt

mspsb9vt1#

.permitAll()意味着允许任何角色,但您仍然使用authenticated()-这意味着用户必须通过Keycloak进行身份验证才能访问。
您可能需要的是以下代码(我还没有测试过,但希望能展示这个想法-您需要一个没有authenticated()的单独块:

http.authorizeHttpRequests(request -> request
                        .requestMatchers("/admins/users/**").hasRole("ADMIN")
                        .requestMatchers("/subscribers/users/**").hasRole("SUBSCRIBER")
                        .anyRequest().authenticated())
.and()
        .authorizeHttpRequests()
                       .requestMatchers("/public/users/**").permitAll()
.and()
        .oauth2ResourceServer()
                .jwt()
                .jwtAuthenticationConverter(authenticationConverter);

相关问题