路由跨域
跨域限制
在进行前后端联调的时候,可能会遇到下面这个报错:
这个错误就是跨域问题,是发生在浏览器端的。浏览器中有一个同源策略,它是一个安全策略,用来限制源的交互。
- 同源策略:是一种约定,它是浏览器核心也最基本的安全功能,它会阻止一个域的 JS 脚本和另外一个域的内容进行交互,如果缺少了同源策略,浏览器很容易受到 XSS、CSFR 等攻击。所谓同源(即在同一个域)就是两个页面具有相同的协议(protocol)、主机(host)和端口号(port)。
- 跨域:当一个请求 URL 的协议、域名、端口三者之间的任意一个与当前页面 URL 不同即为跨域。
场景示例
下面来看一个具体的跨域问题的场景。
创建 flask_cors_demo.py
# 后端服务代码
from flask import Flask
app = Flask(__name__)
@app.route('/hello')
def hello():
return "hello world"
if __name__ == '__main__':
app.run(debug=True, port=5055)
templates 目录下创建 cors.html
<!-- 前端代码 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>跨域问题</title>
</head>
<body>
<div>
<button class="button" id="hello">click me</button>
</div>
</body>
</html>
<script type="text/javascript">
var btnHello = document.querySelector("button#hello");
btnHello.onclick = () => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
xhr.withCredentials = true;
xhr.open("get", "http://localhost:5055/hello", true);
xhr.setRequestHeader("Content-Type", "text");
xhr.send();
};
</script>
启动后端服务后,去访问前端页面,当点击按钮的时候,可以看到控制台报错:
解决跨越问题
cors 是一个 w3c 的标准,全称为跨域资源共享,允许浏览器向跨域服务器发出请求。
- 安装 flask-cors:
pip install flask-cors
- 解决跨域问题分为两种
- 针对全局所有的 API
CORS(app)
- 针对特定的 API
@cross_origin()
-
from flask import Flask
from flask_cors import CORS, cross_originapp = Flask(__name__)
# 第一种:全局解决跨域问题
CORS(app, supports_credentials=True)
# 第二种:局部解决跨域问题
# @cross_origin(supports_credentials=True)
@app.route('/hello')
def hello():
return "hello world"
if __name__ == '__main__':
app.run(debug=True, port=5555) - 跨域也可以结合蓝图去使用:
-
from flask import Flask, Blueprint
from flask_cors import cross_origin, CORS
app = Flask(__name__)
# 第一种:全局解决跨域问题
CORS(app, supports_credentials=True)hello_route = Blueprint("hello", __name__, url_prefix="/hello")
# 第二种:局部解决跨域问题
# @cross_origin(supports_credentials=True)
# @app.route('/hello')
@hello_route.route("")
def hello():
return "hello world"
if __name__ == '__main__':
app.register_blueprint(hello_route)
app.run(debug=True, port=5055) - 这样就可以解决前端报跨域错误的问题了。
- 针对全局所有的 API