如何通过zuul添加或修改请求参数

zuul添加或修改请求参数

一、为什么要用到这个

在基于 springcloud 构建的微服务系统中,通常使用网关zuul来进行一些用户验证等过滤的操作,比如 用户在 header 或者 url 参数中存放了 token ,网关层需要 用该 token 查出用户 的 userId ,并存放于 request 中,以便后续微服务可以直接使用而避免再去用 token 查询。

二、基础知识

在 zuul 中最大的用法的除了路由之外,就是过滤器了,自定义过滤器需实现接口 ZuulFilter ,在 run() 方法中,可以用

RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();

获取到 request,但是在 request 中只有 getParameter() 而没有 setParameter() 方法,所以直接修改 url 参数不可行,另外在 reqeust 中虽然可以使用 setAttribute() ,但是可能由于作用域的不同,在这里设置的 attribute 在后续的微服务中是获取不到的,因此必须考虑另外的方式。

三、具体做法

最后确定的可行的方法是,用

ctx.setRequest(new HttpServletRequestWrapper(request) {})

的方式,重新构造上下文中的 request ,代码如下:

// 例如在请求参数中添加 userId
try {
  InputStream in = ctx.getRequest().getInputStream();
  String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
  if(StringUtils.isBlank(body)){
    body = "{}";
  }
  JSONObject jsonObject = JSON.parseObject(body);
  jsonObject.put("userId", 666);
  String newBody = jsonObject.toString();
  final byte[] reqBodyBytes = newBody.getBytes();
  ctx.setRequest(new HttpServletRequestWrapper(request){
    @Override
    public ServletInputStream getInputStream() throws IOException {
      return new ServletInputStreamWrapper(reqBodyBytes);
    }
    @Override
    public int getContentLength() {
      return reqBodyBytes.length;
    }
    @Override
    public long getContentLengthLong() {
      return reqBodyBytes.length;
    }
  });
} catch (IOException e) {
  e.printStackTrace();
}

思路就是,获取请求的输入流,并重写,即重写json参数。

在后续的微服务的 controller 中,通过下面的方式获取通过zuul添加或修改的请求参数。

InputStream in = request().getInputStream();
String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
if(StringUtils.isNotBlank(body)){
  JSONObject jsonObject = JSON.parseObject(body);
  Object userId = jsonObject.get("userId");
}

zuul修改请求url

除了修改请求参数、设置响应header,响应body外,还有一种需求就是url重新,或者是修改url,这里简述一下怎么在zuul修改url。

转发配置

demo:
  ribbon:
    NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
    listOfServers: 192.168.99.100,192.168.99.101
zuul:
  routes:
    demo:
      path: /demo/**
      stripPrefix: true
      serviceId: demo

filter配置

@Component
public class UrlPathFilter extends ZuulFilter{
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }
    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
    }
    @Override
    public boolean shouldFilter() {
        final String serviceId = (String) RequestContext.getCurrentContext().get("proxy");
        return "demo".equals(serviceId);
    }
    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        Object originalRequestPath = context.get(FilterConstants.REQUEST_URI_KEY);
        //http://localhost:10000/demo/list/data
        //-->/api/prefix/list/data
        String modifiedRequestPath = "/api/prefix" + originalRequestPath;
        context.put(FilterConstants.REQUEST_URI_KEY, modifiedRequestPath);
        return null;
    }
}

这样就大功告成了!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • zuulGateway 通过filter统一修改返回值的操作

    使用spring cloud有时候我们给客户端返回内容的时候,往往需要添加一些额外的东西.比如加密,多添加一个返回值等等. 当然可以在方法里面处理,但如果方法很多,需要统一处理的,就很不方便了,这时候可以通过zuulGateway的filter来统一处理. 直接看代码,很简单: import java.io.InputStream; import java.nio.charset.Charset; import org.springframework.cloud.netflix.zuul.fil

  • SpringCloud通用请求字段拦截处理方法

    背景 以SpringCloud构建的微服务系统为例,使用前后端分离的架构,每个系统都会提供一些通用的请求参数,例如移动端的系统版本信息.IMEI信息,Web端的IP信息,浏览器版本信息等,这些参数可能放在header里,也可以放在参数里,如果这些参数需要在每个方法内声明定义,一来工作量太大,二是这些通用参数与业务接口方法耦合过紧,本身就是一个不好的设计. 这个问题该如何优雅地解决呢? 最佳实践 利用SpringMVC提供拦截器,对匹配的请求,抽取通用的header信息(假设通用字段全部放在hea

  • springcloud 中 zuul 修改请求参数信息的方法

    Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器. Zuul功能: 认证 压力测试 金丝雀测试 动态路由 负载削减 安全 静态响应处理 主动/主动交换管理 Zuul的规则引擎允许通过任何JVM语言来编写规则和过滤器, 支持基于Java和Groovy的构建. 配置属性 zuul.max.host.connections 已经被两个新的配置属性替代, zuul.host.maxTotalConnections (总连接数)和 zuul.host.maxPerRouteConnec

  • 详解SpringCloud Zuul过滤器返回值拦截

    Zuul作为网关服务,是其他各服务对外中转站,通过Zuul进行请求转发.这就涉及到部分数据是不能原封返回的,比如服务之间通信的凭证,用户的加密信息等等. 举个例子,用户服务提供一个登录接口,用户名密码正确后返回一个Token,此Token作为用户服务的通行证,那么用户登录成功后返回的Token就需要进行加密或者防止篡改处理.在到达用户服务其他接口前,就需要对Token进行校验,非法的Token就不需要转发到用户服务中了,直接在网关层返回信息即可. 要修改服务返回的信息,需要使用的是Zuul的过滤

  • spring cloud zuul增加header传输的操作

    spring cloud zuul增加header传输 在使用OAuth2.0传输权限认证,为了再调用其他的项目的时候获取token,必须在token下传到其他各个服务 @Component public class KeyUserFilter extends ZuulFilter { private static final Logger logger = LoggerFactory.getLogger(KeyUserFilter.class); @Override public Object

  • 如何通过zuul添加或修改请求参数

    zuul添加或修改请求参数 一.为什么要用到这个 在基于 springcloud 构建的微服务系统中,通常使用网关zuul来进行一些用户验证等过滤的操作,比如 用户在 header 或者 url 参数中存放了 token ,网关层需要 用该 token 查出用户 的 userId ,并存放于 request 中,以便后续微服务可以直接使用而避免再去用 token 查询. 二.基础知识 在 zuul 中最大的用法的除了路由之外,就是过滤器了,自定义过滤器需实现接口 ZuulFilter ,在 ru

  • spring cloud zuul修改请求url的方法

    前言 在日常开发中,除了修改请求参数.设置响应header,响应body外,还有一种需求就是url重新,或者是修改url,这里简述一下怎么在zuul修改url.话不多说了,来一起看看详细的介绍吧. 转发配置 demo: ribbon: NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList listOfServers: 192.168.99.100,192.168.99.101 zuul: ro

  • Spring MVC请求参数与响应结果全局加密和解密详解

    前提 前段时间在做一个对外的网关项目,涉及到加密和解密模块,这里详细分析解决方案和适用的场景.为了模拟真实的交互场景,先定制一下整个交互流程.第三方传输(包括请求和响应)数据报文包括三个部分: 1.timestamp,long类型,时间戳. 2.data,String类型,实际的业务请求数据转化成的Json字符串再进行加密得到的密文. 3.sign,签名,生成规则算法伪代码是SHA-256(data=xxx&timestamp=11111),防篡改. 为了简单起见,加密和解密采用AES,对称秘钥

  • webview添加参数与修改请求头的user-agent实例

    前言 最近公司项目需求,在项目中嵌入h5页面,一般原生,看着感觉跟往常一样,一个地址就完全ok了,如果是这样那就没有这个博文的必要了! 项目的登录使用的token登录,在移动端的登录是原生的,但是h5也是有登录页面,这就需要控制token的过期时间了,但是想达到的网页访问使用网页的cookie,app登录使用的是app原生的登录token,在网页的cookie登录过期的时候,网页是可以正常退回登录页面,而在app嵌入的h5也需要根据token是否过期,决定是否返回登录页. 那么,问题就是在此产生

  • SpringBoot2.1.3修改tomcat参数支持请求特殊符号问题

    最近遇到一个问题,比如GET请求中,key,value中带有特殊符号,请求会报错,见如下URL: http://xxx.xxx.xxx:8081/aaa?key1=val1&a.[].id=123&b=a[1] 现在,我们进入boot启动类,添加如下代码即可: public class DemoApp { public static void main(String[] args) { SpringApplication.run(DemoApp.class, args); } @Bean

  • Android WebView通过动态的修改js去拦截post请求参数实例

    需求背景: 需要在用户点击提交按钮的时候拦截用户提交的数据. 遇到的问题: 1.页面不是自家前端做的,不能修改网页中的代码 2.要拦截的请求不是get请求,而是一个post请求 (难点在于:如果拦截的请求是get请求的话,我只需要拿到url,将后面拼接的参数键值对取出来就好了,但是post请求的参数键值对我们是看不到的...) 解决重点: 重写webViewClient的shouldInterceptRequest这个方法 1.这个方法是API21以后才出现的,还有一个过时的方法也要重写,不要忘

  • AngularJS出现$http异步后台无法获取请求参数问题的解决方法

    本文实例讲述了AngularJS出现$http异步后台无法获取请求参数问题的解决方法.分享给大家供大家参考,具体如下: angular在通过异步提交数据时使用了与jQuery不一样的请求头部和数据序列化方式,导致部分后台程序无法正常解析数据. 原理分析(网上的分析): 对于AJAX应用(使用XMLHttpRequests)来说,向服务器发起请求的传统方式是:获取一个XMLHttpRequest对象的引用.发起请求.读取响应.检查状态码,最后处理服务端的响应.整个过程示例如下: var xmlht

  • PHP中Http协议post请求参数

    本文给大家介绍PHP中Http协议post请求参数,具体内容如下所示: WEB开发中信息基本全是在POST与GET请求与响应中进行,GET因其基于URL的直观,易被我们了解,可POST请求因其信息的隐蔽,在安全的同时,也给开发者们模拟发送带来了麻烦.接下来的几篇博文中,我将结合自己的笔记和理解,详细解释PHP进行POST请求的几种方法,如有错误,烦请指正. HTTP协议信息是WEB开发中的一项重要内容,了解它可以帮助我们更深刻地理解BS交互,也有利于我们从更底层理解WEB开发.HTTP协议是一种

  • php+mysqli预处理技术实现添加、修改及删除多条数据的方法

    本文实例讲述了php+mysqli预处理技术实现添加.修改及删除多条数据的方法.分享给大家供大家参考.具体分析如下: 首先来说说为什么要有预处理(预编译)技术?举个例子:假设要向数据库添加100个用户,按常规思路,就是向数据库发送100个执行请求,此时,按照 mysql 数据库的工作原理,它需要对每一条执行语句进行编译(这里就有100次).所以,这里的效率是非常低的. 预处理(预编译)技术的作用,就是减少编译的次数和时间,以提高效果.通过一个案例来说明,预处理(预编译)技术是如何做到的(好吧,先

随机推荐