【问题标题】:Netflix Zuul - block request routingNetflix Zuul - 阻止请求路由
【发布时间】:2016-09-11 14:54:11
【问题描述】:

使用 Zuul,我可以轻松定义在请求转发到特定服务之前或之后激活的自定义过滤器。

有没有办法阻止请求在“预”过滤级别转发,并立即将响应发送给客户端? 我知道使用“静态”过滤器可以进行类似的操作,但我需要根据请求来决定(基于请求本身中是否存在某些参数/标头)。

【问题讨论】:

    标签: netflix-zuul


    【解决方案1】:

    这是我如何使用 zuul-filter 来检查 API 密钥是否被授权的示例。如果没有,我会向客户端发送 401 响应。

     @Override
        public Object run() {
    
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
    
            String apiKey = request.getHeader("X-API-KEY");
            if (!isAuthorized(apiKey)){
                // blocks the request
                ctx.setSendZuulResponse(false);
    
                // response to client
                ctx.setResponseBody("API key not authorized");
                ctx.getResponse().setHeader("Content-Type", "text/plain;charset=UTF-8");
                ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            }
    
            return null;
        }
    

    请注意,如果客户端的 API 密钥未授权,所有其他过滤器仍将运行,但请求仍会因ctx.setSendZuulResponse(false) 而失败。 当响应失败时,默认情况下它将为空 - 也就是说,没有诸如 Content-Type 之类的标头。最好自己设置它们,以便客户端的浏览器等知道如何解析响应正文。

    【讨论】:

    • 在确定请求未授权后执行更多过滤器感觉有点低效。是否有另一种方法可以优雅地中止进一步执行并简单地返回错误代码,也可能在响应正文中返回错误消息?
    • 在过滤器中抛出异常是否有效,例如ZuulException 或 ZuulRuntimeException,然后在 SendErrorFilter(filterType 为“error”的过滤器)中捕获异常?也许programcreek.com/java-api-examples/…的一些代码示例可以使用。
    • @Dojo 您可能已经考虑过它,但只想指出,对于所有后续过滤器,您可以使 shouldFilter() 方法返回 false,例如通过检查 sendZuulResponse 是否已经被伪造 - 我猜你的目标是不考虑更多过滤器并立即向客户端返回响应。
    • 是的,我正在寻找一种方法来立即“中止”对过滤器的任何进一步评估并返回响应。 shouldFilter() 方法听起来不错。我完全怀念那样看它。
    【解决方案2】:

    我使用pre 过滤器检查请求的身份验证,如果请求未授权,则返回401 并且不再调用后端服务。我在run() 函数中这样做:

        RequestContext ctx = getCurrentContext();
        // do something to check the authentication
        if(auth failed){
          ctx.unset();
          ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
    

    ctx.unset()告诉上下文停止这个请求,ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());设置http代码为401

    【讨论】:

      【解决方案3】:

      我找到了解决办法,只需要添加context.setSendZuulResponse(false); 在我的“pre”自定义过滤器的 run() 方法中。

      仍会调用其他过滤器,但不会将请求路由到目的地。

      【讨论】:

      • 有没有办法避免进一步的过滤器执行?这感觉有点低效。如果其他过滤器调用 context.setResponseBody,也不尊重 context.setSendZuulResponse(false);然后你仍然会得到回应。
      猜你喜欢
      • 2020-05-06
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      • 2020-10-30
      • 2016-11-16
      • 2016-06-15
      • 2022-10-24
      相关资源
      最近更新 更多