如何从 webfilter 中的 oauth2 令牌中提取 accountId

How to extract accountId from oauth2 token in webfilter

我在我的程序中使用 webflux 和 oauth2 安全性 (keycloack as UAA server) 我想从 oauth2 jwt 中提取一些信息并且我做得很好。但我需要在过滤器中获取一些信息。 当我使用我的旧方法时,它在 filter (WebFilter) 中不起作用。 有没有办法解析令牌并从中获取信息? 我的方法是正确的还是我应该使用 springSecurityFilterChain 而不是 WebFilter 来提取它? 我想检查令牌中的 accountId 和客户端使用过滤器发送的 url 中的 accountId。

听说是我提取 accountId 的代码,它在 WebFilter 中不起作用,但当我使用它时它可以工作服务或控制器

  public class SecurityFilter implements WebFilter {
    
    
        @Override
        public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
           ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication).map(Principal::getName).filter((accountId) -> accountId.equals(clientAccountId)

.switchIfEmpty(Mono.error(new SystemException("401 ERROR")));;
          return webFilterChain.filter(serverWebExchange);
    
    }

听说是我提取accountId的第二种方法:

public class SecurityFilter implements WebFilter {


    @Override
    public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
      serverWebExchange.getPrincipal().map(Principal::getName).filter((accountId) -> accountId.equals(clientAccountId). .switchIfEmpty(Mono.error(new SystemException("401 ERROR")));;
      return webFilterChain.filter(serverWebExchange);

}

我的安全配置是:

 @Bean
    SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                .authorizeExchange()
                .pathMatchers("/api/**").authenticated()
              //  .pathMatchers("/**").permitAll()
                .anyExchange().authenticated()
                .and()
                .exceptionHandling()
                .accessDeniedHandler(new HttpStatusServerAccessDeniedHandler(HttpStatus.BAD_REQUEST))
                .and()
                .oauth2ResourceServer()
                .jwt()
                .jwtAuthenticationConverter(grantedAuthoritiesExtractor());
        return http.build();
    }
     

我想我应该有另一个 SecurityWebFilterChain 方法来为我做这个 ??

您正在寻找这样的东西

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    var clientAccountId = "clientId";
    return exchange.getPrincipal()
            .map(Principal::getName)
            .flatMap((accountId) -> {
                if (accountId.equals(clientAccountId) && exchange.getRequest().getPath().value().equals("/my/api")) {
                    return Mono.just(accountId);
                }
                return Mono.error(new IllegalArgumentException("401 ERROR"));
            })
            .flatMap(tokenJwt -> chain.filter(exchange))
            .onErrorResume(r -> {
                exchange.getResponse().setRawStatusCode(HttpStatus.UNAUTHORIZED.value());
                return exchange.getResponse().setComplete();
            });
}

注意:当你使用反应式时,直到你或spring订阅它,它才会被执行。