CORS ( 跨来源资源共享 )

因为同源政策( Same-origin policy ) 的存在,限制了程式码( 特别是Ajax ) 和不同网域资源间的互动。这样的设计是为了安全,防范骇客的攻击!但也因此让笔者的本地html 无法使用云端的Web API,因为对本地html 而言,Web API 是跨来源的资源。

那么如何在某些特定情况下,才能让跨来源的资源被允许存取呢?那就是靠CORS( Cross-Origin Resource Sharing ),它能让网页的受限资源被其他网域的页面存取。通过该机制,页面能够自由地使用不同网域的图片、样式、指令码、iframes 以及影片。

总结:CORS 是一份浏览器技术的规范,提供了Web 服务从不同网域传来沙盒指令码的方法,以避开浏览器的同源政策。

Flask-SocketIO 实现CORS 的方法

当我把Web API 放到云端上后,本地html 去连线云端的Web API,会出现以下错误:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
1634629850436.jpg

错误讯息主要是说明:在请求的资源上没有Access-Control-Allow-Origin 标头值,这导致origin 值为null,而这样的情况下会被CORS 政策阻止。

如果该资源是允许被任何人存取的( 就像所有透过GET 方法存取的HTTP 资源),则需要回传带有Access-Control-Allow-Origin 标头值的回应即可。所以接下来笔者要示范,如何在Flask-SocketIO 进行CORS。

因为Flask-SocketIO 很贴心地有提供 cors_allowed_origins 需要给予的参数:(2) 单一List,设置多个被允许的origin。(3) 特殊值,设置所有origin 都被允许。但使用特殊值 要格外小心,因为这会使Server 容易受到跨站请求的伪造攻击( CSRF )。

Flask 实现CORS 的方法

pip install Flask-Cors

Flask-Cors,提供了两种方式:全域方式、装饰器方式。
先来讲最简单的用法,就是使用"全域方式",from flask_cors import CORS,我们把CORS 给引入进来使用。CORS(app),是允许所有路由( route )上的所有网域进行CORS。

from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route("/")
def helloWorld():
    return "Hello, cross-origin-world!"

如果不想允许所有路由( route )上的所有网域进来的话,我们可以做一些设定,来限制符合条件的: route 或origin 才能进来。像是底下例子,route 必须符合/api/ 才会进来,所以def list_users 此函式是可以顺利return “user example”。

from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
@app.route("/api/v1/users")
def list_users():
    return "user example"

第二种方式,就是装饰器方式。顾名思义它就是撰写在装饰器(@)上。方法是在@app.route(..) 底下加入@cross_origin()。而只有底下有加@cross_origin() 的路由( route ),才能允许使用CORS。

from flask import Flask
from flask_cors import cross_origin
@app.route("/")
@cross_origin()
def helloWorld():
    return "Hello, cross-origin-world!"


最后修改:2021 年 10 月 19 日
如果觉得我的文章对你有用,请随意赞赏