我正在尝试将用户保留在超文本传输协议会话中,并使用自定义过滤器验证网关内的身份验证请求。我也发现了类似的问题:
@Configuration
public class SecurityConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(
ServerHttpSecurity http,
MyAuthenticationFilter myAuthenticationFilter
) {
http
.csrf()
.disable()
.authorizeExchange()
.pathMatchers("/**")
.permitAll()
.and()
.addFilterAt(myAuthenticationFilter, SecurityWebFiltersOrder.FIRST); // custom filter
return http.build();
}
@Component
public class MyAuthenticationFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
exchange.getSession().map(
session -> {
session.getAttributes().put("userId", "id123");
// It does not print anything
System.out.println("userId in session: " + session.getAttribute("userId"));
return session;
}
);
return chain.filter(exchange);
}
}
通过添加自定义过滤器,并尝试读取/写入会话属性,正如我在调试模式下观察到的那样,map()
中的函数永远不会被执行,并且终端中没有任何东西被打印出来。(毫不奇怪,下游服务无法从会话中读取userId
,即使网关和服务共享同一个会话)。
为什么不起作用?这里有一个最小的复制版本:Github repo,请查看。
通过设置一个servlet应用程序作为下游服务来做授权,然后读/写会话内部的“授权服务”将相对容易(因为网关和直接下游服务将共享同一个会话)。
至于微服务架构中的整个身份验证/授权部分,我发现使用JWT更可取,建议服务之间应该是无状态的,而网关可以是有状态的,以便与所述的“授权服务”共享会话。
一个很好的答案,直观地解释JWT实现。