【问题标题】:Adding Headers to Zuul when re-directing重定向时向 Zuul 添加标头
【发布时间】:2018-10-07 00:26:33
【问题描述】:

我正在尝试使用Zuul 将调用重定向到其他地方的下游系统。 在重定向中,我需要添加一个包含必要数据的标题,以便api 接收重定向以进行处理。我似乎无法让下游系统检测到这些数据。附上我的代码。 我正在使用来自Edgware.SR3, Spring Boot 1.5.12Zuul

祖尔过滤器

@Component
public class RouteFilter extends ZuulFilter{

@Override
public Object run() {
//Testing to add header
    context.getRequest().getParameterMap().put("api", new String[]{"api"});
    context.getResponse().setHeader("api", api);
    context.addZuulResponseHeader("api", "api");
    context.addZuulRequestHeader("api", "api");
    context.setSendZuulResponse(false);
    context.put(FORWARD_TO_KEY, redirect_urls.get(key));
    context.setResponseStatusCode(HttpStatus.SC_TEMPORARY_REDIRECT);
    context.getResponse().sendRedirect(redirect_urls.get(key));
    return null;
}
}

重定向的服务代码

@RequestMapping(value = "/forward")
public ResponseEntity<String> forwardToMe(@RequestHeader(required = true, name = "api")String api){
    return new ResponseEntity<String>("Hi",HttpStatus.OK);
}

在 Postman 中收到错误

{ “时间戳”:1524737817729, “状态”:400, "error": "错误请求", “异常”:“org.springframework.web.bind.ServletRequestBindingException”, "message": "String 类型的方法参数缺少请求标头 'api'", "路径": "/forward" }

【问题讨论】:

  • sendRedirect 不会传递您提供的任何自定义标头。 context.addZuulXXXHeader 仅用于正常路由。
  • 谢谢,我注意到了。因此询问是否有人在 Zuul Redirects 中操作标头的经验更好。

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


【解决方案1】:

我猜你使用了 Route Filter,也许你可以尝试使用 Pre Filter

添加自定义标题可以通过以下方式完成:context.addZuulRequestHeader("Authorization", "Basic " + credentials);

重定向部分可以查看thread

【讨论】:

  • 我确实有一个预过滤器设置,并且我确实将数据添加到标题中,就像您在预过滤器中所做的那样。没有任何数据通过端点,但在过滤器之间起作用。我确实做了一个解决方法来解决我面临的这个问题。
  • 你能解决这个问题吗?我也面临同样的问题。
  • @Bocky 你做了什么来解决这个问题?
【解决方案2】:

我在这里更新我的评论,以防万一有人仍然面临这个问题。 我最近发现了这个问题并通过在我的application.yml中添加以下配置来解决

application.yml ... zuul: sensitive-headers: - Cookie,Set-Cookie ...

参考链接如下:
https://cloud.spring.io/spring-cloud-static/Dalston.SR5/multi/multi__router_and_filter_zuul.html

【讨论】:

    【解决方案3】:

    我的回复有点晚,但工作正常
    参考官方文档Cookies and Sensitive Headers
    sensitiveHeaders 为黑名单,默认不为空。因此,to make Zuul send all headers (except the ignored ones), you must explicitly set it to the empty list如果您想将 cookie 或授权标头传递到后端,这样做是必要的。下面的例子展示了如何使用sensitiveHeaders:

    zuul:
      routes:
        entry:
          path: /users/**
          strip-prefix: false
          service-id: users-service
          sensitive-headers:
          - Cookie,Set-Cookie
    

    这个实现了example也可以帮到你

    【讨论】:

      【解决方案4】:

      如果有人仍然面临这个问题,

      在 Zuul Proxy 中,将 header 添加到 RequestContext 中,如下所示:

      RequestContext ctx = RequestContext.getCurrentContext();
      ctx.addZuulRequestHeader("param", "value");
      

      然后在各自的微服务中编写自定义过滤器并提取如下值

      @Component
      public class MyFilter extends OncePerRequestFilter {
      
          @Override
          protected void doFilterInternal(HttpServletRequest request,
                                      HttpServletResponse response,
                                      FilterChain filterChain)
                                      throws ServletException, IOException {
      
              String headerParam  =   request.getHeaders("param").nextElement();
          
              logger.info("headerParam: "+headerParam);
          
              filterChain.doFilter(request, response);
          }
      
      }
      

      【讨论】:

        【解决方案5】:
        RequestContext ctx = RequestContext.getCurrentContext();
            String auth = "useeerrr" + ":" + "passsss";
            ctx.addZuulRequestHeader("Authorization", "Basic " +
                    Base64Variants.MIME_NO_LINEFEEDS.encode(auth.getBytes(StandardCharsets.US_ASCII)));
            ctx.addZuulRequestHeader("X-USERNAME-HEADER","xxx");
        
            Map<String, List<String>> newParameterMap = new HashMap<>();
            Map<String, String[]> parameterMap = ctx.getRequest().getParameterMap();
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                String key = entry.getKey();
                String[] values = entry.getValue();
                newParameterMap.put(key, Arrays.asList(values));
            }
           
            String authenticatedKey = "authenticated";
            String authenticatedValue = "true";
            newParameterMap.put(authenticatedKey,Arrays.asList(authenticatedValue));
            ctx.setRequestQueryParams(newParameterMap);
            HttpServletRequest request = ctx.getRequest();
        
            logger.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
        
            return null;
        

        【讨论】:

        • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
        猜你喜欢
        • 2015-08-20
        • 2021-03-09
        • 2018-03-17
        • 1970-01-01
        • 2015-10-25
        • 2015-11-18
        • 2010-10-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多