Zuul关于跨域问题的解决方案之一

前后分离之zuul过滤器处理跨域

刚毕业的应届小白一枚
最近想要自己熟悉一下最近流行的web技术
打算用 spring cloud +vue3 +iview 搭建一个前后分离的项目玩玩
下面是项目地址:
https://github.com/quaint-ai/Vue-SpringCloud-CMS

有一个simple-v1.0 分支,是一个简单的项目结构demo,感兴趣的可以clone到本地尝试一下。有疑问欢迎留言,一起成长。

最近两天遇到了前端请求后端的跨域问题,传统的jsonp不能满足更多的请求方式,因此了解一下cors的方式跨域是必要的。

简要了解cors的跨域原理

个人摸索理解,如果需要改正,请指出。多谢。

为什么需要跨域

  1. 浏览器的同源策略来起到安全的作用。
  2. 需要同协议,同域名/IP,同端口才能直接请求。
  3. 这个协议的存在,我们无法正常跨域请求。

利用cors跨域会有以下过程。

  1. 跨域请求会先发送一个预请求OPTIONS
  2. 预请求成功后需要返回给前端一个成功的状态码
  3. 预请求通过,进行真正的请求,实现跨域

问题解决过程:

前端正常发送ajax/axios请求

import axios from "axios"
const webtest = 'http://localhost:80';
const axiosInstance = axios.create({
    headers: {'Content-Type': 'application/json;charset=utf-8'},// 设置传输内容的类型和编码
    withCredentials: true // 指定某个请求应该发送凭据。允许客户端携带跨域cookie,也需要此配置
  });
// 查询样例用户列表 用于测试
export const testUser = (params) => {
    return axiosInstance({
        url: webtest + "/api/user/1",
        method: "get",
        data: params
    })
}

后端zuul网关处理跨域问题

@Component
public class TokenFilter extends ZuulFilter {


    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE; // 可以在请求被路由之前调用  pre
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER-1; // filter执行顺序,通过数字指定 ,优先级为0,数字越大,优先级越低
    }

    @Override
    public boolean shouldFilter() {
        return true;// 是否执行该过滤器,此处为true,说明需要过滤
    }

    @Override
    public Object run() {
        // 获取request对象
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpServletResponse response = ctx.getResponse();

		// 这些是对请求头的匹配,网上有很多解释
        response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials","true");
        response.setHeader("Access-Control-Allow-Methods","GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH");
        response.setHeader("Access-Control-Allow-Headers","authorization, content-type");
        response.setHeader("Access-Control-Expose-Headers","X-forwared-port, X-forwarded-host");
        response.setHeader("Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers");

        // 跨域请求一共会进行两次请求 先发送options 是否可以请求
        // 调试可发现一共拦截两次 第一次请求为options,第二次为正常的请求 eg:get请求
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())){
            ctx.setSendZuulResponse(false); //验证请求不进行路由
            ctx.setResponseStatusCode(HttpStatus.OK.value());//返回验证成功的状态码
            ctx.set("isSuccess", true);
            return null;
        }
        // 第二次请求(非验证,eg:get请求不会进到上面的if) 会走到这里往下进行
        // 不需要token认证
        ctx.setSendZuulResponse(true); //对请求进行路由
        ctx.setResponseStatusCode(HttpStatus.OK.value());
        ctx.set("isSuccess", true);
        return null;
    }

}

第一个options请求:
Zuul关于跨域问题的解决方案之一_第1张图片
第二个正常请求:

Zuul关于跨域问题的解决方案之一_第2张图片
请求到的数据
Zuul关于跨域问题的解决方案之一_第3张图片
上面是可以成功访问的代码。

下面说一下容易遇到的问题:

当我们注释掉if 让options 直接请求路由,会发生什么?
Zuul关于跨域问题的解决方案之一_第4张图片
会出现下面的提示,大概意思就是 options没有返回 一个成功的状态码,但是上面代码确实有
ctx.setResponseStatusCode(HttpStatus.OK.value());
ctx.set(“isSuccess”, true);
这是卡我一下午一直很疑惑的地方,而且zuul也没有报错,调试发现只有一个options请求,没有收到get请求,可能就是他继续路由出现了异常,没有返回状态码,即使调换代码顺序也还是下面的错误。
Zuul关于跨域问题的解决方案之一_第5张图片

下面这个错误就是后端什么都没有配置,出现的错误,大概意思就是
请求的资源上不存在“Access-Control-Allow-Origin”标头。
就是这些没有配置,后端不认你的远程请求地址
在这里插入图片描述

那今天就到这里吧,如果有问题,在继续研究完善。

你可能感兴趣的:(Zuul,跨域)