zoukankan      html  css  js  c++  java
  • SpringCloud微服务Zuul跨域问题

    目前项目结构是VUE做前端,后端采用微服务架构,在开发时前端需要跨域请求数据,通过ZuulFilter配置解决了简单跨域请求需要。但当需要在请求的header中增加token信息时,出现了请求失败的情况,浏览器和后台均出现OPTIONS类型请求相关提示。

    Failed to load http://192.168.1.149:8000/server/addressbook/delete: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values 'http://192.168.1.242:5500, http://192.168.1.242:5500', but only one is allowed. Origin 'http://192.168.1.242:5500' is therefore not allowed access.

    这里其实已经很明确了,说头包含多个值,只允许一个然后我们看请求信息

    为什么会这样呢?其实是我们在使用ZuulFilter的时候获取的 RequestContext 他给我们自带了 Access-Control-Allow-Origin,Access-Control-Allow-Credentials 这两个参数,所以我们在程序里面就不需要加了

    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.zuul.mgzuul.util.JwtHelperUtil;
    import com.zuul.mgzuul.util.RedisUtil;
    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 javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * @Author 唐银
     * @Description //TODO
     * @Date 2018-01-03 14:20
     * @ClassName MyFilter
     * @ClassNotes
     **/
    @Slf4j
    @Component
    public class MyFilter extends ZuulFilter {
    
        @Resource
        private RedisUtil redisUtil;
    
        @Autowired
        private JwtHelperUtil jwtHelperUtil;
    
        @Override
        public String filterType() {
            /*
            pre:可以在请求被路由之前调用
            route:在路由请求时候被调用
            post:在route和error过滤器之后被调用
            error:处理请求时发生错误时被调用
            * */
            // 前置过滤器
            return FilterConstants.PRE_TYPE;
    
        }
    
        @Override
        public int filterOrder() {
    
            //// 优先级为0,数字越大,优先级越低
            return 0;
        }
    
        @Override
        public boolean shouldFilter() {
    //        RequestContext ctx = RequestContext.getCurrentContext();
    //        HttpServletRequest request = ctx.getRequest();
    //        //过滤各种POST请求
    //        if(request.getMethod().equals(RequestMethod.OPTIONS.name())){
    //            return true;
    //        }
            return true;
    
        }
    
        @Override
        public Object run() {
    
            System.out.println("*****************PostFilter run start*****************");
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletResponse response = ctx.getResponse();
            HttpServletRequest request = ctx.getRequest();
            //response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin")); //这里注释掉
            //response.setHeader("Access-Control-Allow-Credentials","true"); //这里注释掉
            response.setHeader("Access-Control-Expose-Headers","X-forwared-port, X-forwarded-host,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,Authorization,Token,accessToken");
            response.setHeader("Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers");
            String accessToken = request.getHeader("accessToken");
            //跨域请求放行
            if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
                ctx.setSendZuulResponse(true);
                ctx.setResponseStatusCode(200);
                System.out.println("*****************PostFilter run end*****************");
                return null;
            }
    
            String url = request.getRequestURI();
            if(url.indexOf("/login")!=-1){
                ctx.setSendZuulResponse(true);
                ctx.setResponseStatusCode(200);
                System.out.println("*****************PostFilter run end*****************");
                return null;
            }
    
            //验证token
            //String accessToken = request.getHeader("accessToken");
            /*String accessToken = request.getParameter("accessToken");
            if(StringUtils.isBlank(accessToken)){
                log.debug("accessToken 不存在!");
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);// 返回错误码
                ctx.setResponseBody("{"result":"token不存在"}");// 返回错误内容
                ctx.set("isSuccess", false);
                return null;
            }
            Object token_ob = redisUtil.get(accessToken);
            if(token_ob == null){
                log.debug("accessToken 已经过期");
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);// 返回错误码
                ctx.setResponseBody("{"result":"token过期"}");// 返回错误内容
                ctx.set("isSuccess", false);
                return null;
            }else {
                Claims claims = jwtHelperUtil.parseJWT(accessToken);
                if(claims == null){
                    log.debug("accessToken 错误");
                    ctx.setSendZuulResponse(false);
                    ctx.setResponseStatusCode(401);// 返回错误码
                    ctx.setResponseBody("{"result":"token错误"}");// 返回错误内容
                    ctx.set("isSuccess", false);
                    return null;
                }
            }
            //通过后更新登陆过期时间
            redisUtil.set(accessToken,accessToken, 259200);*/
            //允许继续路由
            ctx.setSendZuulResponse(true);
            ctx.setResponseStatusCode(200);
            System.out.println("*****************PostFilter run end*****************");
            return null;
        }
    }

    注释掉以后ok 就成功解决了 (注意在zuul做了跨域设置就不需要在各个服务再做了不然也是会出现这个问题的

    QQ群:216868740

  • 相关阅读:
    双向(端)链表、栈、队列
    WPF 3D基础(1)
    静态查找
    栈和队列 迷宫求解
    异步编程Demo
    WPF 3D基础(2)
    串操作
    链栈和链队
    Linux恢复数据
    word文件修复窍门
  • 原文地址:https://www.cnblogs.com/tangyin/p/10307891.html
Copyright © 2011-2022 走看看