关于SpringCloud Zuul 拦截修改后转发

四季 1年前 ⋅ 2955 阅读

在近期的项目开发过程,因客户方为自封装SpringBoot微服务模式的框架,且通信模式为Grpc,导致内部封装后的 SpringBoot 原始很多特性都不支持(这个很坑,没办法(客户嘛,甲方嘛)每一家都想要搞自己的标准),为了能够很好的支持客户已有的技术标准我们进行整体的改造,将框架的底层算是釜底抽薪改了个彻底。 在此感谢团队内部各位小伙伴的辛苦付出。 在改造的期间碰到的一些问题,我这里也会记录一下主要是为了防止后续有人还会继续踩坑,也为后续有这种需求的人提前做一些参考资料 下面代码片段为,springCloud zuul 拦截参数,修改后,并转发至客户方的API 统一网关,通过zuul本人的路由机制,将相同的url 直接转发至客户方的路由管控中心,进行实际地址的请求

	package com.xxx.filter.forward;
    import com.alibaba.fastjson.JSONObject;
    import com.xxx.common.LoginConstant;
    import com.xxx.common.WebProperties;
    import com.xxx.utils.StringUtils;
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.http.HttpServletRequestWrapper;
    import com.netflix.zuul.http.ServletInputStreamWrapper;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import.org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StreamUtils;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    import java.io.InputStream;
    import java.nio.charset.Charset;

    import static com.netflix.zuul.context.RequestContext.getCurrentContext;

    /**
     * 请求参数拼接
     * 参数拼接后转发
     */
    @Slf4j
    @Component
    public class RequestForwardPreFilter extends ZuulFilter {


        @Autowired
        WebProperties webProperties;

        /**
         * 修改请求参数
         *
         * @return
         */
        @Override
        public Object run() {
            //未开启直接转发,微服务中将接收不到UserCode相关的用户信息
            if (!webProperties.isEnableForwad()) {
                return null;
            } else {
                RequestContext ctx = getCurrentContext();
                HttpServletRequest request = ctx.getRequest();
                String body = "";
                try {
                    InputStream stream = request.getInputStream();
                    body = StreamUtils.copyToString(stream, Charset.forName("UTF-8"));
                    JSONObject object = JSONObject.parseObject(body);
                    String userInfo = this.getUserInfo(request);
                    object.put(LoginConstant.LOGIN_KEY, userInfo);
                    body = object.toString();
                    //转发参数重置
                    final byte[] reqBodyBytes = body.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) {
                    log.error("",e.getMessage());
                }
            }
            return null;
        }

        /**
         * 组织客户端用户信息
         *
         * @param request
         * @return
         */
        private String getUserInfo(HttpServletRequest request) {
            String remoteAddr = StringUtils.getRemoteAddr(request);
            String proxyName = request.getHeader(LoginConstant.LOGIN_AGENT);
            String userInfo = (String) request.getSession().getAttribute(LoginConstant.LOGIN_KEY);
            JSONObject object = JSONObject.parseObject(userInfo);
            object.put("remoteAddr", remoteAddr);
            object.put("proxyName", proxyName);
            return object.toJSONString();
        }

        @Override
        public boolean shouldFilter() {
            return true;
        }

        @Override
        public int filterOrder() {
            return 1;
        }

        @Override
        public String filterType() {
            return FilterConstants.ROUTE_TYPE;
        }
    }

注意FilterType类型需要定义为 ROUTE_TYPE 过程类型,否则将不会生效。


全部评论: 0

    我有话说: