首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Spring Cloud Gateway的GlobalFilter中从SecurityContext中获取BearerTokenAuthentication

如何在Spring Cloud Gateway的GlobalFilter中从SecurityContext中获取BearerTokenAuthentication
EN

Stack Overflow用户
提问于 2021-05-01 14:15:17
回答 1查看 153关注 0票数 3

Spring Cloud Gateway作为OAuth2ResourceServer,授权配置如下:

代码语言:javascript
复制
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http
        .authorizeExchange(exchanges ->
            exchanges
                .anyExchange().authenticated()
        )
        .oauth2ResourceServer(OAuth2ResourceServerSpec::jwt)
    return http.build();
}

我有一个全局过滤器,它负责对每个有效的身份验证请求执行一些功能,如下所示:

代码语言:javascript
复制
@Service
public class CustomGlobal implements GlobalFilter {

    @Autowired
    BearerTokenAuthentication authentication;
    
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // access request headers, and perform some logic

        // extract details from the JWT token, and perform some logic
        log.info(authentication.getTokenAttributes.get("sub")); 

        // ^ in the above line there's a NullPointerException, since instance 
        // BearerTokenAuthentication is not set, or not visible at a GlobalFilter class
        

        return chain.filter(exchange);
    }
}

我还处于学习阶段。任何可能的线索都将不胜感激。

EN

回答 1

Stack Overflow用户

发布于 2021-05-05 08:04:43

我这样做了(请注意,您应该将WebFilter更改为GlobalFilter)。

添加到你的pom中

代码语言:javascript
复制
 <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
            <version>5.4.6</version>
        </dependency> 

那么过滤器应该是这样的

代码语言:javascript
复制
package filter;

import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.*;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

@Log4j2
public class CustomGlobal implements WebFilter {
    public static final String HEADER_PREFIX = "Bearer ";
    private final ReactiveJwtDecoder jwtDecoder;

    public ReactiveJwtDecoder createDecoder(String issuer, String jwkUrl) {
        var jwtDecoder = NimbusReactiveJwtDecoder.withJwkSetUri(jwkUrl).build();
        jwtDecoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>(
                new JwtIssuerValidator(issuer),
                new JwtTimestampValidator()));
        return jwtDecoder;
    }

    protected CustomGlobal(String issuer, String jwkUrl) {
        this.jwtDecoder = createDecoder(issuer, jwkUrl);
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return Mono
                .defer(() -> {
                    var token = resolveToken(exchange.getRequest());
                    if (!StringUtils.hasText(token)) {
                        throw new BadJwtException("Authorisation token is invalid");
                    }
                    return jwtDecoder.decode(token);
                })
                .flatMap(tokenJwt -> {
                    log.info(tokenJwt.getClaimAsString("sub"));
                    return chain.filter(exchange);
                })
                .onErrorResume(err -> handleError(exchange));
    }


    private Mono<Void> handleError(ServerWebExchange exchange) {
        exchange.getResponse().setRawStatusCode(HttpStatus.UNAUTHORIZED.value());
        exchange.getResponse().getHeaders().add("Content-Type", "application/json");
        return exchange.getResponse().setComplete();
    }

    private String resolveToken(ServerHttpRequest request) {
        String bearerToken = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(HEADER_PREFIX)) {
            return bearerToken.substring(7).trim();
        }
        return "";
    }
}

下一步是创建配置

代码语言:javascript
复制
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;


@Configuration
public class CustomGlobalConfig {
    @Value("${jwt.iss}")
    private String issuer;
    @Value("${jwt.jwk-uri}")
    private String jwkUrl;


    @Bean
    CustomGlobal createFilterBean() {
        return new CustomGlobal(this.issuer, this.jwkUrl);
    }

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67343406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档