Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS #14

Open
YBFACC opened this issue Jun 8, 2020 · 0 comments
Open

CORS #14

YBFACC opened this issue Jun 8, 2020 · 0 comments
Labels

Comments

@YBFACC
Copy link
Owner

YBFACC commented Jun 8, 2020

CORS

跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求

引用来自MDN

我的完整代码

简单请求和复杂请求

两者的区别在于:是否需要发送预检请求。

满足以下条件就可以不需要发送预检请求👇

  • 使用以下方法之一:
    • GET
    • POST
    • HEAD
  • Header头不超过以下几种:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type包含以下几种:
      • text/plain
      • multipart/form-data
      • application/x-www-form-urlencoded
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width

简单请求测试

使用axios库来简化ajax操作。

发送一个get请求

当我们像平常一样发送 GET 请求时,会出现跨域报错。

1

解决的方法就是加上Access-Control-Allow-Origin:*这个 Header。

2

可以看到我们的跨域请求正常收到了。

其实你可以通过服务端的日志看到,其实服务端是正常返回的。浏览器帮你拦截了这个请求。

带 Cookie 的 GET 请求

axios 需要打开 withCredentials: true (默认为false)

const api = axios.create({
  timeout: 1000,
  withCredentials: true
});

3

可以看到报错了。这里需要我们将Access-Control-Allow-Origin:指定明确的域名。

5

还是报错这里需要我们加上另一个 Header Access-Control-Allow-Credentials 为 true。

80

可以看到请求正常了。

客户端需要获取服务端设置的 Header

你在服务端设置 Header

ctx.res.setHeader('X-Custom-Header',"TestCors")

然后客户端打印下可以拿到的 Header

100

可以看到确实没有拿到我们需要的 Haeder。我们需要指定 Access-Control-Expose-Headers

ctx.res.setHeader('Access-Control-Expose-Headers', 'X-Custom-Header')

客户端再次打印可以拿到的 Header。

1

可以看到我们需要的 Header已经正常了。

复杂请求测试

复杂请求需要在正式请求前加一个 Haeder。

我们可以看看一个服务端的日志。

3

发送了2次请求:一次预检、一次正式请求。

我们发送一个 PUT 请求

我们把客户端和服务端都设置成 PUT。

5

我们需要将 Access-Control-Allow-Methods设置成 PUT。(这里最好返回所有支持的方法,以免多次预检)

1

我们可以在 Network 中看到 OPTIONS 请求。

2

可以看到 PUT 请求请求正常。

减少发送预检的次数

我们可以设置 Access-Control-Max-Age 来设置预检的有效期。

ctx.res.setHeader('Access-Control-Max-Age', '30')

打印服务端的日志👀来看清每次请求

3

当超过设置的时间后,再次请求。可以看到又请求了。

30

客户端需要获取服务端设置的 Header

同上

服务端获取客户端设置的 Header

我们在客户端设置 Header,然后在服务端获取。

const api = axios.create({
  timeout: 1000,
  headers: { 'X-Custom-Header': 'foobar' }
});

我们可以看到报错了。

1

这里我们需要指定 Access-Control-Allow-Headers

ctx.res.setHeader('Access-Control-Allow-Headers', 'X-Custom-Header')
//省略一些代码
ctx.req.headers['x-custom-header']

1

可以看到我们获取了客户端设置的 Header。

关于 Access-Control-Request-Headers

引用MDN来自:请求头 **Access-Control-Request-Headers **出现于 preflight request(预检请求)中,用于通知服务器在真正的请求中会采用哪些请求头。

没试出作用😰。

关于跨域的误区

  1. ✕ 动态请求就会有跨域的问题

✔ 跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/ java等其它环境

  1. ✕ 跨域就是请求发不出去了

✔ 跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了

引用来自我知道的跨域与安全

参考

HTTP访问控制(CORS)

跨域资源共享 CORS 详解

@YBFACC YBFACC added the Http label Jun 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant