赞
踩
跨域是指:浏览器A从服务器B获取的静态资源,包括Html、Css、Js,然后在Js中通过Ajax访问C服务器的静态资源或请求。即:浏览器A从B服务器拿的资源,资源中想访问服务器C的资源。
同源策略是指:浏览器A从服务器B获取的静态资源,包括Html、Css、Js,为了用户安全,浏览器加了限制,其中的Js通过Ajax只能访问B服务器的静态资源或请求。即:浏览器A从哪拿的资源,那资源中就只能访问哪。
同源是指:同一个请求协议(如:Http或Https)、同一个Ip、同一个端口,3个全部相同,即为同源。
W3C组织制定了一个Cross-Origin Resource Sharing规范,简写为Cors,现在这个规范已经被大多数浏览器支持,Cors 专门用来处理跨域的需求。
Cors需要在后端应用进行配置,因此,是一种跨域的后端处理方式,这么做也容易理解,一个你不认识的源来访问你的应用,自然需要应用进行授权。除了后端处理方式,也有前端的解决方案,如:JSONP,这里我们主要讲解Flask后端配置方案.
跨域分为以下3种
| 名称 | 英文名 | 说明 |
|---|---|---|
| 简单请求 | Simple Request | 发起的Http请求符合: 1.无自定义请求头,只有Accept、Accept-Language、Content-Language、Last-Event-ID 2.请求动词为GET、HEAD或POST之一 3.动词为POST时,Content-Type是application/x-www-form-urlencoded,multipart/form-data或text/plain之一 |
| 复杂请求 | Preflighted Request | 发起的Http请求符合其中之一: 1.包含了自定义请求头 2.请求动词不是GET、HEAD或POST 3.动词是POST时, Content-Type不是application/x-www-form-urlencoded,multipart/form-data或text/plain。 即:简单请求的相反 |
| 凭证请求 | Requests with Credential | 发起的Http请求中带有凭证 |
简单请求的发送从代码上来看和普通的XHR没太大区别,但是HTTP头当中要求总是包含一个域(Origin)的信息。该域包含协议名、地址以及一个可选的端口。不过这一项实际上由浏览器代为发送,并不是开发者代码可以触及到的。
简单请求的部分响应头如下:
如果仅仅是简单请求,那么即便不用CORS也没有什么大不了,但CORS的复杂请求就令CORS显得更加有用了。简单来说,任何不满足上述简单请求要求的请求,都属于复杂请求。比如说你需要发送PUT、DELETE等HTTP动作,或者发送Content-Type: application/json的内容。
复杂请求先发送一种"预请求",此时作为服务端,也需要返回"预回应"作为响应。预请求实际上是对服务端的一种权限请求,只有当预请求成功返回,实际请求才开始执行。预请求以OPTIONS形式发送,当中同样包含域,并且还包含了两项CORS特有的内容:
显而易见,这个预请求实际上就是在为之后的实际请求发送一个权限请求,在预回应返回的内容当中,服务端应当对这两项进行回复,以让浏览器确定请求是否能够成功完成。复杂请求的部分响应头及解释如下:
一旦预回应如期而至,所请求的权限也都已满足,则实际请求开始发送。
目前大部分Modern浏览器已经支持完整的CORS,但IE直到IE11才完美支持,所以对于PC网站,还是建议采用其他解决方案,如果仅仅是移动端网站,大可放心使用。
flask 配置cors 有两种方式,一种使用自带的cors,一种自定义返回头
- @app.after_request
- def af_request(resp):
- """
- #请求钩子,在所有的请求发生后执行,加入headers。
- :param resp:
- :return:
- """
- resp = make_response(resp)
- resp.headers['Access-Control-Allow-Origin'] = '*'
- resp.headers['Access-Control-Allow-Methods'] = 'GET,POST'
- resp.headers['Access-Control-Allow-Headers'] = 'x-requested-with,content-type'
- return resp
Flask配Cors跨域,使用Flask-CORS包,详细文档,参见: https://flask-cors.readthedocs.io/en/latest/
flask-cors 也提供了两种方式:
| 方式 | 范围 | 说明 |
|---|---|---|
| @cross_origin装饰器 | 配置单个路由 | 适用于配置特定的API接口 |
| CORS函数 | 配置全局API接口 | 适用于全局的API接口配置 |
安装flask-cors
pip install flask-cors
第一种:使用@cross_origin装饰器
- @app.route("/")
- @cross_origin()
- def helloWorld():
- return "Hello, cross-origin-world!"
CORS参数说明
| 装饰器参数 | 类型 | Head字段 | 说明 |
|---|---|---|---|
| origins | 列表、字符串或正则表达式 | Access-Control-Allow-Origin | 配置允许跨域访问的源, |
| methods | 列表、字符串 | Access-Control-Allow-Methods | 配置跨域支持的请求方式,如:GET、POST |
| expose_headers | 列表、字符串 | Access-Control-Expose-Headers | 自定义请求响应的Head信息 |
| allow_headers | 列表、字符串或正则表达式 | Access-Control-Request-Headers | 配置允许跨域的请求头 |
| supports_credentials | 布尔值 | Access-Control-Allow-Credentials | 是否允许请求发送cookie,false是不允许 |
| max_age | 整数、字符串 | Access-Control-Max-Age | 预检请求的有效时长 |
第二种:使用CORS函数
- #################### 应用全局配置 ####################
- from flask_cors import *
-
-
- app = Flask(__name__)
- CORS(app, supports_credentials=True, resources=r"/*")
-
- @app.route("/api/v1/users")
- def list_users():
- return "user example"
-
-
- #################### 单独Blueprints配置 ####################
- api_v1 = Blueprint('API_v1', __name__)
- CORS(api_v1)
-
- @api_v1.route("/api/v1/users/")
- def list_users():
- return "user example"

CORS参数说明
| 参数 | 类型 | Head字段 | 说明 |
|---|---|---|---|
| resources | 字典、迭代器或字符串 | 无 | 全局配置允许跨域的API接口 |
| origins | 列表、字符串或正则表达式 | Access-Control-Allow-Origin | 配置允许跨域访问的源, |
| methods | 列表、字符串 | Access-Control-Allow-Methods | 配置跨域支持的请求方式,如:GET、POST |
| expose_headers | 列表、字符串 | Access-Control-Expose-Headers | 自定义请求响应的Head信息 |
| allow_headers | 列表、字符串或正则表达式 | Access-Control-Request-Headers | 配置允许跨域的请求头 |
| supports_credentials | 布尔值 | Access-Control-Allow-Credentials | 是否允许请求发送cookie,false是不允许 |
| max_age | 整数、字符串 | Access-Control-Max-Age | 预检请求的有效时长 |
继承Resource类来写的RESTful-API接口不能使用上述办法。解决办法是在需要支持跨域请求的API类下,添加一个类方法options,就可以解决跨域问题
原因是跨域问题请求的时候,无论是POST请求还是PUT请求,前端都会优先发起一个OPTIONS请求确认请求允许范围.那么在解决跨域请求时,只需要在每个资源url中加入options请求方式,并返回适当的响应头信息就能解决跨域问题.
- class YourAPI(Resource):
- def options(self):
- return {'Allow': '*'}, 200, {'Access-Control-Allow-Origin': '*',
- 'Access-Control-Allow-Methods': 'HEAD, OPTIONS, GET, POST, DELETE, PUT',
- 'Access-Control-Allow-Headers': 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild',
- }
具体可配置参数解释:
Access-Control-Allow-Origin
这个头部信息由服务器返回,用来明确指定那些客户端的域名允许访问这个资源。它的值可以是:
-使用" * " —— 允许任意域名
如果你需要客户端传递验证信息到头部(比如:cookies)。这个值不能为 * —— 必须为完整的域名(这点很重要)。
Access-Control-Allow-Credentials
这个头部信息只会在服务器支持通过cookies传递验证信息的返回数据里。它的值只有一个就是 true。跨站点带验证信息时,服务器必须要争取设置这个值,服务器才能获取到用户的cookie。
Access-Control-Allow-Headers
提供一个逗号分隔的列表表示服务器支持的请求数据类型。假如你使用自定义头部(比如:x-authentication-token 服务器需要在返回OPTIONS请求时,要把这个值放到这个头部里,否则请求会被阻止)。
Access-Control-Expose-Headers
相似的,这个返回信息里包含了一组头部信息,这些信息表示那些客户端可以使用。其他没有在里面的头部信息将会被限制(译者注:这个头信息实战中使用较少)。
Access-Control-Allow-Methods
一个逗号分隔的列表,表明服务器支持的请求类型(比如:GET, POST)
Origin
这个头部信息,属于请求数据的一部分。这个值表明这个请求是从浏览器打开的哪个域名下发出的。出于安全原因,浏览器不允许你修改这个值。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。