Flask 开启跨域
安装 flask-cors
pip install flask-cors
设置允许跨域
开启全局允许跨域
示例
from flask_cors import CORS
CORS(app, supports_credentials=True)
CORS 的参数
参数 | 类型 | Head字段 | 说明 | 默认 |
---|---|---|---|---|
resources | 字典、迭代器或字符串 | 无 | 全局配置允许跨域的API接口 | 全部 |
origins | 列表、字符串或正则表达式 | Access-Control-Allow-Origin | 配置允许跨域访问的源,* 表示全部允许 | * |
methods | 列表、字符串 | Access-Control-Allow-Methods | 配置跨域支持的请求方式,如:GET、POST | [GET,HEAD,POST,OPTIONS,PUT,PATCH,DELETE] |
expose_headers | 列表、字符串 | Access-Control-Expose-Headers | 自定义请求响应的Head信息 | None |
allow_headers | 列表、字符串或正则表达式 | Access-Control-Request-Headers | 配置允许跨域的请求头 | * |
supports_credentials | 布尔值 | Access-Control-Allow-Credentials | 是否允许请求发送cookie,False是不允许,True是允许 | False |
max_age | 整数、字符串 | Access-Control-Max-Age | 预检请求的有效时长 | None |
设置单条路由允许跨域
示例
from flask_cors import *
@app.route('/')
@cross_origin(supports_credentials=True)
def hello():
name = request.args.get("name", "World")
return f'Hello, {name}!'
cross_origin 的参数
装饰器参数 | 类型 | Head字段 | 说明 | 默认 |
---|---|---|---|---|
resources | 字典、迭代器或字符串 | 无 | 全局配置允许跨域的API接口 | 全部 |
origins | 列表、字符串或正则表达式 | Access-Control-Allow-Origin | 配置允许跨域访问的源,* 表示全部允许 | * |
methods | 列表、字符串 | Access-Control-Allow-Methods | 配置跨域支持的请求方式,如:GET、POST | [GET,HEAD,POST,OPTIONS,PUT,PATCH,DELETE] |
expose_headers | 列表、字符串 | Access-Control-Expose-Headers | 自定义请求响应的Head信息 | None |
allow_headers | 列表、字符串或正则表达式 | Access-Control-Request-Headers | 配置允许跨域的请求头 | * |
supports_credentials | 布尔值 | Access-Control-Allow-Credentials | 是否允许请求发送cookie,False是不允许,True是允许 | False |
max_age | 整数、字符串 | Access-Control-Max-Age | 预检请求的有效时长 | None |
注意事项
关于发送Cookie
CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。
CORS(app, supports_credentials=True)
另一方面,开发者必须在AJAX请求中打开withCredentials属性。
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
否则,即使服务器同意发送Cookie,浏览器也不会发送。或者,服务器要求设置Cookie,浏览器也不会处理。
需要注意的是,如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。
CORES(app,origins = ['example1','example2'])
同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。
关于预检
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT
或DELETE
,或者Content-Type
字段的类型是application/json
。
非简单请求的CORS
请求,会在正式通信之前,增加一次HTTP
查询请求,称为"预检"请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest
请求,否则就报错
"预检"请求用的请求方法是OPTIONS
,表示这个请求是用来询问的。头信息里面,关键字段是Origin
,表示请求来自哪个源。
除了Origin字段,"预检"请求的头信息包括两个特殊字段。
Access-Control-Request-Method
该字段是必须的,用来列出浏览器的CORS
请求会用到哪些HTTP方法,上例是PUT
。Access-Control-Request-Headers
该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header
。
服务器收到"预检"请求以后,检查了Origin
、Access-Control-Request-Method
和Access-Control-Request-Headers
字段以后,确认允许跨源请求,就可以做出回应。
拓展
在预检的时候,OPTIONS
的请求不会携带cookie和请求的参数,正式请求才会携带Cookie、参数。
postman 模拟跨域请求
- 在请求头添加
origin = 127.0.0.1
- 查看返回的请求头信息中,是否包含允许跨域信息
Access-Control-Allow-Origin = 127.0.0.1
Access-Control-Allow-Credentials = true
Vary = Origin