欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

重写HttpServletRequest的Header

程序员文章站 2024-02-04 14:02:58
...

如何重写HttpServletRequest的Header

场景

在使用网关对请求头中的token进行鉴权之后,希望将鉴权后的用户信息,写入到request的header中;此时,一般的HttpServletRequest是没有提供直接写入header的方法的。

此时或许有人会退而求其次,不将信息放到header中,而放到key-value参数里面;但如果我们的服务使用的是JSON格式接收数据,相关信息就不太好处理了。所以建议还是放到请求头里去。

方案

虽然HttpServletRequest没有直接提供addHeader的方法,但是HttpServletRequestWrapper已经实现了HttpServletRequest的接口,故我们可以通过自定义子类继承HttpServletRequestWrapper,重写getHeaders的方法,再将自定义子类充当 HttpServletRequest返回或 放入上下文RequestContext中即可。

自定义子类

/**
 * 自定义子类,核心点在于自定义header的map,再重写获取header的方法,将自定义的map也一起返回
 * 重写HttpServletRequest的请求头
 * @author: songwenguang
 * @time: 2021/3/17 14:11
 */
@Slf4j
public class HeaderMapRequestWrapper extends HttpServletRequestWrapper {

    /**
     * 构造方法,可保持原有的request内容不变
     *
     * @param request
     */
    public HeaderMapRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    // 用于存放自定义header的map
    private Map<String, String> headerMap = new HashMap<>();

    /**
     * 在header中添加key-value
     */
    public void addHeader(String key, String value) {
        headerMap.put(key, value);
    }

    @Override
    public String getHeader(String name) {
        log.info("getHeader --->{}",name);
        String headerValue = super.getHeader(name);
        if (headerMap.containsKey(name)) {
            headerValue = headerMap.get(name);
        }
        return headerValue;
    }

    /**
     * 需要重写的方法,即获取请求头Key时,加上自定义请求头内容的key
     * get the Header names
     */
    @Override
    public Enumeration<String> getHeaderNames() {
        List<String> names = Collections.list(super.getHeaderNames());
        for (String name : headerMap.keySet()) {
            names.add(name);
        }
        return Collections.enumeration(names);
    }

    /**
     * 需要重写的方法,获取所有的header参数时,添加上自定义header的map
     * get the Header key-value
     */
    @Override
    public Enumeration<String> getHeaders(String name) {
        List<String> values = Collections.list(super.getHeaders(name));
        if (headerMap.containsKey(name)) {
            values = Arrays.asList(headerMap.get(name));
        }
        return Collections.enumeration(values);
    }

}

1、上下文RequestContext中

    /**
     * 此处使用的时Zuul网关中的过滤器,获取到上下文RequestContext对象,
     * 修改完Request后再通过setRequest修改
     */
    @Override
	public Object run() {
		RequestContext ctx = RequestContext.getCurrentContext();
		ctx.getResponse().setCharacterEncoding("UTF-8");
		HttpServletRequest request = ctx.getRequest();

		//将上下文RequestContext需要透传的参数封装到 HttpServletRequest 的header中
		HeaderMapRequestWrapper hw = new HeaderMapRequestWrapper(request);
		hw.addHeader("userId", "1");
		hw.addHeader("account", "admin");
		ctx.setRequest(hw);
		return null;
	}

2、也可以在自定义Filter中返回

public class MyFilterOne implements Filter {
 
    /**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		
	}
	
	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}
	
	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		HeaderMapRequestWrapper hw = new HeaderMapRequestWrapper(request);
		hw.addHeader("userId", "1");
		hw.addHeader("account", "admin");
		//直接将自定义的request返回
		chain.doFilter(hw, response);
	}
 
}