【问题标题】:Spring boot 2 Microservices - Propagate the Principal to servicesSpring boot 2 微服务 - 将主体传播到服务
【发布时间】:2019-10-22 05:08:35
【问题描述】:

我正在开发一个使用 spring boot、spring cloud 和 Zuul 作为网关的应用程序。

使用 Spring Security,我创建了一个授权服务,该服务将在用户登录时生成 JWT 令牌。

Zuul 网关可以解码此令牌,并让请求在我的应用程序内部发送到路由服务。

现在的问题是,如何在其中一个微服务中获取登录用户(或令牌本身)?有没有办法告诉 Zuul 网关将令牌附加到他传递给路由路径的每个请求?

所有微服务都没有 Spring Security 作为依赖项,因为我们的想法是只在网关级别检查令牌,而不是到处检查令牌,但我找不到合适的方法来这样做......

假设我有一个在网关中路由的用户服务。登录后,用户想要查看他的个人资料。

他将使用令牌向{{gateway_url}}/getUser 发出请求。

网关配置是

zuul:
  ignored-services: '*'
  sensitive-headers: Cookie,Set-Cookie
  routes:
    user-service:
      path: /user/**
      service-id: USER-SERVICE

网关会将此请求路由到 USER-SERVICE 应用程序,到 getProfile 控制器方法我如何知道哪个是登录用户?谁提出的要求?

【问题讨论】:

  • 下游服务应该得到适当的 HTTP 标头。
  • 下游消息中没有标头...看起来网关没有随请求发送任何内容
  • 你期待什么标题?
  • 最好的应该是 jwt

标签: spring-boot spring-cloud netflix-zuul


【解决方案1】:

敏感头是黑名单,默认不为空。因此,要让 Zuul 发送所有头文件(除了被忽略的头文件),您必须将其显式设置为空列表。如果您想将 cookie 或授权标头传递到后端,则必须这样做。下面的例子展示了如何使用sensitiveHeaders:

application.yml:

 zuul:
  routes:
    users:
      path: /myusers/**
      sensitiveHeaders:
      url: https://downstream

【讨论】:

    【解决方案2】:

    现在的问题是,我怎样才能获得登录用户(或令牌 本身)在其中一个微服务中?有没有办法告诉Zuul 网关将令牌附加到他传递给路由的每个请求 路径?

    您可以在 zuul 路由请求之前将任何自定义标头添加到请求中, 看看这段代码:

    @Configuration
    public class ZuulCustomFilter extends ZuulFilter {
    
        private static final String ZULL_HEADER_USER_ID = "X-Zuul-UserId";
    
        @Override
        public String filterType() {
            return FilterConstants.PRE_TYPE;
        }
    
        @Override
        public int filterOrder() {
            return 0;
        }
    
        @Override
        public boolean shouldFilter() {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            return authentication != null && authentication.getPrincipal() != null;
        }
    
        @Override
        public Object run() throws ZuulException {
            if (
                SecurityContextHolder.getContext().getAuthentication().getPrincipal() != null &&
                SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof OnlineUser
                ) {
    
                OnlineUser onlineUser = (OnlineUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
                RequestContext ctx = RequestContext.getCurrentContext();
    
                ctx.addZuulRequestHeader(ZULL_HEADER_USER_ID, onlineUser.getId());
    
            }
            return null;
        }
    }
    

    在这个示例中,用户的 id 被附加到请求中,然后被路由到相应的服务。 这个过程发生在spring security执行用户授权之后

    【讨论】:

    • 您的网关需要路由请求。它不应包含任何与安全相关的逻辑。它不应该承担多重责任。
    • 好吧,我不觉得将 spring zuul 和 spring security 集成到一个微服务中被认为是一种不好的做法。
    猜你喜欢
    • 2022-01-15
    • 2019-02-11
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 2020-03-11
    • 2022-01-08
    • 2020-09-27
    • 2019-02-20
    相关资源
    最近更新 更多