1. 概述

我们在平台中使用feign调用服务时,我们提供了一个 TokenRelayRequestIntecepor 的拦截器。这个拦截器负责从当前请求中获取 token 信息,并将这个token信息在发送调用的请求中。

相关代码如下:

HttpServletRequest request = attributes.getRequest();
String auth=request.getHeader(SecurityConstants.Authorization);
// 2. 将token传递
if (StringUtils.isNotBlank(auth)) {
    requestTemplate.header(SecurityConstants.Authorization, auth);
}

所以在有些情况下,我们的token并不是直接通过 请求头进行传递的。比如是从第三方通过URL传递过来。因此我们需要 在当前的 request 对象中加入 请求头。但是HttpServletRequest并没有 增加请求头的方法。JAVE SERVLET 规范提供了 装饰模式支持我们对 HttpServletRequest 进行扩展。

2. 实现步骤

2.1 增加一个装饰类

public class HeadMapRequestWrapper extends HttpServletRequestWrapper {
    public HeadMapRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    private Map<String, String> headerMap = new HashMap<>();

    /**
     * add a header with given name and value
     *
     * @param name
     * @param value
     */
    public void addHeader(String name, String value) {
        headerMap.put(name, value);
    }

    @Override
    public String getHeader(String name) {
        String headerValue = super.getHeader(name);
        if (headerMap.containsKey(name)) {
            headerValue = headerMap.get(name);
        }
        return headerValue;
    }

    /**
     * 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);
    }

    @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);
    }
}

这个类继承自 HeadMapRequestWrapper 类。

我们在这个类中增加了 addHeader的方法。

2.2 修改过滤器对request进行包装

HttpServletRequest request=(HttpServletRequest)servletRequest;
HeadMapRequestWrapper requestWrapper = new HeadMapRequestWrapper(request);
filterChain.doFilter(requestWrapper, servletResponse);

这样上下文的 request 对象实际上是包装过的对象实例。

2.3 在代码中使用

HttpServletRequest request = servletRequestAttributes.getRequest();
HeadMapRequestWrapper wrapper=(HeadMapRequestWrapper)request;
wrapper.addHeader("Authorization","Bearer "+ token);

从上下文获取request 对象,并转换成 HeadMapRequestWrapper 类型,调用 addHeader方法。 这样调用 feign 就能够将 验证token发送需要调用的服务了。

文档更新时间: 2021-04-15 09:29   作者:zyg