CORS跨源资源共享

CORS跨源资源共享

当我通过axios向目标url发送请求时候出现下面报错:

访问拒绝

Javascript代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
axios({
url : "https://jwxt.zufe.edu.cn/jwglxt/cjcx/cjcx_cxXsgrcj.html?doType=query&gnmkdm=N305005",
headers : {
"User-Agent": "123",
"Cookie": "123"
},
data : {
"xnm": "2023",
"xqm": "3",
"queryModel.showCount": "15"
},
method:'GET',
}).then(result=>{
console.log(result);
})

可以看到我的http请求被拒绝了。而在Status中我们可以看到CORS error这是什么?

什么是CORS?

CORS(跨源资源共享)是一种机制,允许服务器指示浏览器允许来自不同源的请求。这通常用于保护资源,确保只有特定网站可以访问 API。那么为什么这里出现了CORS的错误呢?

由于不同源

首先要有CORS这个出现(而你用request请求就不会)就是因为我们是不同源。比如

1
2
http://123.com:8080
http://321.com:8080

这里就是host不一样(或者你端口不一样,http和https不一样),这就是不同源,也就是说网站不能直接共享另一个网站的数据,除非另一个网站有其他配置。那么何为同源?比如

1
2
http://123.com:8080
http://123.com:8080/abab

那么它就和是同源的。因此,我现在的网站文件要么就是本地服务器源,要么就是file源,总之不和目标源一样。

为什么python的request请求就可以?

由上一篇文章知道,我们的python是可以正常获取的。这是因为python不在浏览器中运行,它属于后端程序,不会触发preflight检测。

何为preflight

如果你要通过这个网站得到目标网站的数据,首先网站不直接发送http请求,而是发送一个http option请求,然后目标网站的服务器会检查这个http option请求。这个过程就叫preflight。

预检查流程

如果目标的服务器有配置这个来处理预检的 OPTIONS 请求,那么目标服务器就会发送一个CORS头请求,这个头请求包括:

  • Access-Control-Allow-Origin:指定允许的源。如果该值与请求源匹配,浏览器会继续执行实际请求。
  • Access-Control-Allow-Methods:列出允许的方法(如 GET、POST)。
  • Access-Control-Allow-Headers:列出允许的自定义请求头。

可以看到目标服务器是可以指定允许的源,允许的方法还有允许的请求头。

然后你的浏览器接收到了这个CORS之后,会自己检查,如果符合的,就不会发送你的http请求(这也是在保护你的数据,总不能什么都不检查就把你的cookie什么发过去吧)。当然如果你的http请求都满足CORS的头请求,那么就会正常发送。

流程如图

这里再看下我的请求:

控制台信息

再结合第一张图的404,可以看出并不是我的请求不满足CORS头请求,而是目标服务器根本没做接收option请求的配置。

另一种思路

如果我们浏览器无法直接请求,那么我是不是可以通过先通过python请求并获取目标服务器数据,然后再将获取的数据部署到本地服务器,然后再让axios去请求本地服务器的数据呢?思路如上图

配置Flask

我们这里直接使用Flask框架来简单的将json数据传入本地服务器,端口就写5000好了。

main文件代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from GetScoreData import send_to_server
from flask import Flask, jsonify

app = Flask(__name__)


@app.route('/data', methods=['GET'])
def get_data():
url = "https://jwxt.zufe.edu.cn/jwglxt/cjcx/cjcx_cxXsgrcj.html?doType=query&gnmkdm=N305005"
headers = {
"User-Agent": "",
"Cookie": ""
}
body = {
"xnm": "2023",
"xqm": "3",
"queryModel.showCount": "15"
}
data = send_to_server(url, headers, body)
print(data)
return jsonify(data)


if __name__ == "__main__":
app.run(port=5000)

发送axios请求

在JavaScript文件中发送请求:

1
2
3
4
5
6
axios({
url:'http://127.0.0.1:5000/data',
method:'GET',
}).then(result=>{
console.log(result);
})

但是这样可能还是有问题:

由于请求过于简单,没有请求体,直接跳过了preflight,返回CORS error

可以看到跟上文所说的一样,端口不一样也会触发preflight预检测,因此我们有两个思路:

  • 更改端口号使其一致
  • 配置CORS

如果配置CORS也非常方便,只需下载flask_cors库并在主文件中写下:

1
2
from flask_cors import CORS
CORS(app) # 允许所有来源访问

即可允许访问。

同样你也可以将端口改成5050,这样也可以成功访问数据。

访问成功


CORS跨源资源共享
https://bayeeaa.github.io/2024/10/20/CORS跨源资源共享/
Author
Ye
Posted on
October 20, 2024
Licensed under