正如标题所述,我面临着允许访问我的微服务架构中应该公开访问的端点的问题。我正在使用Keycloak进行基于角色的身份验证,它工作得很好,除了在访问公共端点时,我一直遇到401 Unauthorized
错误,尽管在我的SecurityFilterChain
Bean中使用了.permitAll()
方法。
需要注意的是,我还使用Spring Clouds API网关将传入请求路由到负载平衡的微服务。
代码和配置类粘贴在下面,但这是我过去几天一直在尝试解决问题的方法。
1.我最初在API网关级别实现了身份验证。然而,无论我尝试什么,当从我的微服务访问端点时,我总是得到401状态,这导致了解决方案尝试2。
1.我在微服务级别实现了身份验证,基于角色的身份验证工作正常,但访问公共端点仍然是一个问题。
1.我尝试在我的微服务SecurityFilterChain
Bean中禁用CSRF,但它也没有改变任何东西。
1.目前,我完全删除了微服务中SecurityFilterChain
Bean的公共端点。相反,我在SecurityWebFilterChain
Bean中的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();
}
}
1条答案
按热度按时间mspsb9vt1#
.permitAll()
意味着允许任何角色,但您仍然使用authenticated()
-这意味着用户必须通过Keycloak进行身份验证才能访问。您可能需要的是以下代码(我还没有测试过,但希望能展示这个想法-您需要一个没有
authenticated()
的单独块: