温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎么给HttpServletRequest增加消息头

发布时间:2021-06-30 09:25:38 来源:亿速云 阅读:406 作者:小新 栏目:开发技术

小编给大家分享一下怎么给HttpServletRequest增加消息头,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

HttpServletRequest增加header

由于在请求中请求域的属性在请求转发,路由等过程中,请求域的值会丢失,在项目项目中使用请求头来传递信息,但是HttpRequest并没有实现增加请求头的方法,所以找到他的子类来实现

 class MutableHttpServletRequest extends HttpServletRequestWrapper {     // holds custom header and value mapping     private final Map<String, String> customHeaders;      public MutableHttpServletRequest(HttpServletRequest request){         super(request);         this.customHeaders = new HashMap<String, String>();     }          public void putHeader(String name, String value){         this.customHeaders.put(name, value);     }       public String getHeader(String name) {         // check the custom headers first         String headerValue = customHeaders.get(name);                  if (headerValue != null){             return headerValue;         }         // else return from into the original wrapped object         return ((HttpServletRequest) getRequest()).getHeader(name);     }       public Enumeration<String> getHeaderNames() {         // create a set of the custom header names         Set<String> set = new HashSet<String>(customHeaders.keySet());                  // now add the headers from the wrapped request object         @SuppressWarnings("unchecked")         Enumeration<String> e = ((HttpServletRequest) getRequest()).getHeaderNames();         while (e.hasMoreElements()) {             // add the names of the request headers into the list             String n = e.nextElement();             set.add(n);         }           // create an enumeration from the set and return         return Collections.enumeration(set);     } }

使用:

public class SecurityFilter implements javax.servlet.Filter {      @Override     public void destroy() {             }       @Override     public void doFilter(ServletRequest request, ServletResponse response,             FilterChain chain) throws IOException, ServletException {         HttpServletRequest req = (HttpServletRequest) request;         MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req);         ...         mutableRequest.putHeader("x-custom-header", "custom value");         chain.doFilter(mutableRequest, response);     }       @Override     public void init(FilterConfig filterConfig) throws ServletException {             } }

但是项目中我使用的SpringCloud ZUUL中使用这样 的方式失败:

@Component public class AccessFilter extends ZuulFilter {     private  Logger log = LoggerFactory.getLogger(AccessFilter.class);     @Autowired     private VerificationHelper helper;     private  BufferedReader reader=null;     @Autowired     private KeyAndFrequencyService service;     @Autowired     private ZuulTest zuulTest;     @Autowired     private PermissionHandler permissionHandler;     @Override     public String filterType() {         //前置过滤器         return "pre";     }     @Override     public int filterOrder() {         //优先级,数字越大,优先级越低         return 0;     }     @Override     public boolean shouldFilter() {         //是否执行该过滤器,true代表需要过滤         return true;     }     @Override     public Object run() {         RequestContext ctx = RequestContext.getCurrentContext();         HttpServletRequest request = ctx.getRequest();         try {             permissionHandler.setTokenExpireTime(200000000);             String type = request.getHeader("type");             zuulTest.say();             System.out.println("......................................................");             if (type == null) {                 System.out.println("......................................................验证1");                 Object object = helper.AccessZuul(request, ctx);                 return object;             } else {                 System.out.println("......................................................验证2");                 PermissionResult result=permissionHandler.check(request);                 System.out.println(result);                 if(result.isState()){            MutableHttpServletRequest  mutRequest=new MutableHttpServletRequest (request);                      //增加头部信息                     DasAccountInfo accountInfo= permissionHandler.GetDasAccountInfoById(Integer.parseInt(result.getUserId()));                                          mutRequest.putHeader("dasAccountInfo", JSON.toJSONString(disablePropertyName()))                   ;RequestContext.getCurrentContext().setRequest(mutRequest);                     ctx.setSendZuulResponse(true);// 对该请求进行路由                     ctx.setResponseStatusCode(200);                     ctx.set("isSuccess", true);                 }else{                     ctx.setSendZuulResponse(false);// 过滤该请求,不对其进行路由                     ctx.setResponseStatusCode(401);// 返回错误码                     ctx.setResponseBody("{\"code\":0,\"result\":\"网关验证失败!验证方式为2\"}");// 返回错误内容                     ctx.set("isSuccess", false);                 }             }         }catch (Exception e){             e.printStackTrace();             log.error("网关报错!!!",e.fillInStackTrace());         }            return null;     }

使用zuul网关的自带的设置请求头的方法,在网关中设置的请求头可以被路由下面的服务获取到:

ctx.getZuulRequestHeaders().put("dasAccountInfo", JSON.toJSONString(disablePropertyName()));

修改HttpServletRequest中header的信息

废话一堆:由于业务有统一的鉴权系统,页面请求时在header中带过来gsid,正常业务没有问题,但是当需要下载文件时,前端统一用json解析响应,当响应文件时,对于前端来说不好处理,就决定使用简单的get请求下载文件,将gsid通过url带过来,这样的话后端鉴权就需要处理,当header中没有gsid时,从参数中取,为了尽可能少的改变公用的业务代码(指sso),就在当前项目中自定义权限拦截器。

总结一句,我就是想想header中加东西!!往下看具体实现方式:

新建拦截器类,继承原有的拦截器,重写其preHandle方法

@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {     String gsid = request.getHeader("GSID");     if(StringUtils.isBlank(gsid)){         String gsid= request.getParameter("GSID");         //使用反射,将gsid设置到request中的的header中去         reflectSetparam(request,"GSID",gsid);         log.info("请求连接中的gsid={}",request.getHeader("GSID"));     }     return super.preHandle(request, response, o); }

说明:可以看到在方法中,

1、先进行header信息判断,如果header中没有GSID,就去请求参数中拿

gsid= request.getParameter("GSID");

2、通过反射将参数中的GSID键值对儿:“GSID”:“376645354562335”加入到header中去

话不多少,先上代码,再解释:

解释:

/**  * 修改header信息,key-value键值对儿加入到header中  * @param request  * @param key  * @param value  */ private void reflectSetparam(HttpServletRequest request,String key,String value){     Class<? extends HttpServletRequest> requestClass = request.getClass();     System.out.println("request实现类="+requestClass.getName());     try {         Field request1 = requestClass.getDeclaredField("request");         request1.setAccessible(true);         Object o = request1.get(request);         Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");         coyoteRequest.setAccessible(true);         Object o1 = coyoteRequest.get(o);         System.out.println("coyoteRequest实现类="+o1.getClass().getName());         Field headers = o1.getClass().getDeclaredField("headers");         headers.setAccessible(true);         MimeHeaders o2 = (MimeHeaders)headers.get(o1);         o2.addValue(key).setString(value);     } catch (Exception e) {         e.printStackTrace();     } }

执行打印信息如下:

request实现类=org.apache.catalina.connector.RequestFacade

coyoteRequest实现类=org.apache.coyote.Request

看HttpServletRequest的源码,是个接口,并且我们获取header信息的方法是getHeader()方法,按常理其对象中应该有header字段,那么我们就去实现类中找这个字段,具体过程如下

步骤一:先找到具体的Request对象是哪个类,根据打印信息看源码

进入其中找到getHeader()方法,如下

public String getHeader(String name) {     if (this.request == null) {         throw new IllegalStateException(sm.getString("requestFacade.nullRequest"));     } else {         return this.request.getHeader(name);     } }

然后我们找this.request

怎么给HttpServletRequest增加消息头

这个request,我们找到它的类型,点击去

怎么给HttpServletRequest增加消息头

这个类的全路径是:org.apache.catalina.connector.Request

这个类中找getHeader方法

public String getHeader(String name) {     return this.coyoteRequest.getHeader(name); }

找到这个类中的coyoteRequest

protected org.apache.coyote.Request coyoteRequest;

是这样的

怎么给HttpServletRequest增加消息头

再找到getHeader()

public String getHeader(String name) {     return this.headers.getHeader(name); }

好了,终于见到属性了

private final MimeHeaders headers = new MimeHeaders();

找到MineHeaders中的getHeader方法,

public String getHeader(String name) {     MessageBytes mh = this.getValue(name);     return mh != null ? mh.toString() : null; }

看到最终header是一个MessageBytes对象,好找到这个对象进去,发现只能setValue,那就在MineHeaders中找在哪里实例化MessageBytes对象的

找了半天找到在createHeader()方法中实例化MimeHeaderField对象,然后这个对象实例化时会实例化MessageBytes对象

怎么给HttpServletRequest增加消息头

这里有name,value,靠谱

然后再在MimeHeader中找在addValue方法中有调用,就用这个试一下吧,然后就是最上面的我自定义的方法,在heade中加入了一个键值对儿。

测试请求:

http://127.0.0.1:32100/v1/CustomerRefundRest/exportRefund?gsid=abc114f1bd0d484084e5df3fe1c419b8&refundLongStartDate=1520611199000&refundLongEndDate=1522943999000

测试打印结果:

怎么给HttpServletRequest增加消息头怎么给HttpServletRequest增加消息头

以上是“怎么给HttpServletRequest增加消息头”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI