将用户 ID 作为下游请求中的标头传递。 Spring Cloud 网关 + Oauth2资源服务器

发布于 2025-01-14 11:05:55 字数 2159 浏览 0 评论 0原文

我想通过将 Spring Cloud 网关服务器设为 oAuth2 资源服务器来实现安全性。这些请求正在根据我的 Spring Security 授权服务器进行身份验证。对于某些请求,我希望将经过身份验证的用户的 userId 作为请求标头传递给下游服务。

这是我的路线:

.route("create-deck", routeSpec -> routeSpec
                    .path("/decks")
                    .and()
                    .method(HttpMethod.POST)
                    .filters(
                            fs -> fs.addRequestHeader("userId", "ADD_USER_ID_HEADER_HERE"))
                    .uri("http://localhost:8082/"))

我已将授权服务器配置为返回 userId 作为主体名称:

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = ur.findByUsername(username);
    if (user == null) {
      log.error("User: {} not found", username);
      throw new UsernameNotFoundException("User: " + username + " not found");
    }

    return new org.springframework.security.core.userdetails.User(String.valueOf(user.getId()), user.getPassword(), authorities);
}

注意:我有一个存储在数据库中的自定义域对象 User。

路由已成功通过身份验证,并且令牌包含 userId 作为主题。我只需要有关如何获取主题并将其作为请求标头传递给下游请求的帮助。

我正在使用以下依赖项:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-oauth2-jose</artifactId>
        <version>5.6.2</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

I want to implement security on my Spring cloud gateway server by making it an oAuth2 resource server. The requests are getting authenticated against my spring security authorization server. For some requests I want to pass the userId of the authenticated user as a request header to my downstream services.

Here's my route:

.route("create-deck", routeSpec -> routeSpec
                    .path("/decks")
                    .and()
                    .method(HttpMethod.POST)
                    .filters(
                            fs -> fs.addRequestHeader("userId", "ADD_USER_ID_HEADER_HERE"))
                    .uri("http://localhost:8082/"))

I have configured my authorization server to return userId as principal name:

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = ur.findByUsername(username);
    if (user == null) {
      log.error("User: {} not found", username);
      throw new UsernameNotFoundException("User: " + username + " not found");
    }

    return new org.springframework.security.core.userdetails.User(String.valueOf(user.getId()), user.getPassword(), authorities);
}

Note: I have a custom domain object User that I store in my database.

The route is getting successfully authenticated and the token contains userId as subject. I just need help on how to get the subject and pass that to my downstream request as a request header.

I am using the following dependencies:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-oauth2-jose</artifactId>
        <version>5.6.2</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故事↓在人 2025-01-21 11:05:55

您可以创建将应用于所有请求的自定义过滤器。以下是 user 是 jwt 令牌一部分的示例。

public class UserHeaderFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return ReactiveSecurityContextHolder.getContext()
                .filter(c -> c.getAuthentication() != null)
                .flatMap(c -> {
                    JwtAuthenticationToken jwt = (JwtAuthenticationToken) c.getAuthentication();

                    String user = (String) jwt.getTokenAttributes().get("user");
                    if (Strings.isNullOrEmpty(user)) {
                        return Mono.error(
                                new AccessDeniedException("Invalid token. User is not present in token.")
                        );
                    }

                    ServerHttpRequest request = exchange.getRequest().mutate()
                            .header("x-user", user).build();

                    return chain.filter(exchange.mutate().request(request).build());
                })
                .switchIfEmpty(chain.filter(exchange));
    }
}

You could create custom filter that will be applied to all requests. Here is an example when user is a part of the jwt token.

public class UserHeaderFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return ReactiveSecurityContextHolder.getContext()
                .filter(c -> c.getAuthentication() != null)
                .flatMap(c -> {
                    JwtAuthenticationToken jwt = (JwtAuthenticationToken) c.getAuthentication();

                    String user = (String) jwt.getTokenAttributes().get("user");
                    if (Strings.isNullOrEmpty(user)) {
                        return Mono.error(
                                new AccessDeniedException("Invalid token. User is not present in token.")
                        );
                    }

                    ServerHttpRequest request = exchange.getRequest().mutate()
                            .header("x-user", user).build();

                    return chain.filter(exchange.mutate().request(request).build());
                })
                .switchIfEmpty(chain.filter(exchange));
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文