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

原文地址:https://www.cnblogs.com/tangyin/p/10307891.html