Nginx+Flask+Ajax跨域请求问题处理

本文详细解析了Ajax跨域问题的成因及解决方案,重点介绍了使用Nginx反向代理和Flask服务端配置来实现跨域请求的方法。

写在前面

  还是和上一篇同一个项目,不过遇到的问题不同,所以分成两篇blog了(假装很高产hhh),这次是Ajax带来的跨域问题,场景是对子域名sub.a.cn发出的请求(80端口)要转发到服务器的1024端口上,对于非Ajax请求没有问题,但Ajax请求会在浏览器控制台抛出错误:SEC7120: [CORS] 原点“http://XXX”未在“http://XXXXXX”的 cross-origin 资源的 Access-Control-Allow-Origin response header 中找到“http://XXX”

Ajax跨域问题

  什么是跨域呢?当客户端通过Ajax方式向服务端发送Ajax请求时,如果客户端和服务端不在一个域(如协议、端口、域名不一致),浏览器出于安全考虑,会对Ajax请求做校验,不通过时会抛出跨域错误(所以是浏览器的锅,并不是服务端的原因

解决方案:

  1. 禁止浏览器做跨域校验(不实际,需要每个用户对浏览器进行操作)
  2. Nginx反向代理做设置,对返回给浏览器的响应加header(让浏览器认为是同个域下的)
  3. 服务端修改,让服务端返回给nginx的响应支持跨域

实现:

  1. nginx(代理)设置:
server{
    listen 80;
    server_name sub.a.cn;

    location / {
        proxy_pass http://localhost:1024;
        add_header Access-Control-Allow-Methods * always;
        add_header Access-Control-Max-Age 3600 always;
        add_header Access-Control-Allow-Credentials true always;


        add_header Access-Control-Allow-Origin $http_origin always;
        add_header Access-Control-Allow-Headers $http_access_control_request_headers always;
    }
}
  1. flask(服务端)设置:
    (1)安装跨域模块pip install flask-cors
    (2)导入模块并设置跨域
from flask import Flask
from flask_cors import *  # 导入模块
app = Flask(__name__)
CORS(app, supports_credentials=True)  # 设置跨域

参考

[1] ajax跨域完全讲解
[2] Ajax跨域问题详解
[3] Flask允许跨域

### 问题解决方案 问题是由于浏览器的安全策略(Same-Origin Policy)引起的,当一个资源试图从不同的名、协议或端口号加载另一个资源时,就会触发限制。以下是几种常见的问题解决方案: #### 1. 使用 CORS 配置 CORS(Cross-Origin Resource Sharing)是一种标准的资源共享机制,通过服务器设置响应头来允许来自其他源的请求。对于基于 Flask 的后端服务,可以通过安装 `Flask-CORS` 扩展来轻松实现这一功能[^2]。 ```python from flask import Flask, jsonify from flask_cors import CORS app = Flask(__name__) CORS(app) @app.route('/data') def get_data(): return jsonify({"message": "This is cross-origin data."}) if __name__ == '__main__': app.run(port=8080) ``` 此方法适用于大多数现代浏览器,并且支持多种 HTTP 方法(如 GET 和 POST),因此推荐作为首选方案。 --- #### 2. JSONP 技术 JSONP 是一种利用 `<script>` 标签绕过同源策略的技术,它可以完成局部刷新并解决问题。然而需要注意的是,JSONP 只能用于 GET 请求,无法发送 POST 或 PUT 等复杂类型的请求[^3]。 以下是一个简单的 JSONP 实现示例: ```html <script> function handleResponse(data) { console.log('Received:', data); } </script> <script src="http://example.com/api/data?callback=handleResponse"></script> ``` 尽管 JSONP 曾经被广泛使用,但由于其局限性和安全性不足,现在已逐渐被淘汰,仅在某些特定场景下仍可考虑。 --- #### 3. 后端代理 另一种常见的方式是在同一源下的后端创建一个代理接口,由该接口转发到目标地址。这种方式完全规避了浏览器层面的限制,同时也增强了系统的安全性和可控性。 例如,在 Node.js 中可以这样实现反向代理: ```javascript const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const app = express(); app.use('/api', createProxyMiddleware({ target: 'http://backend-server.example.com', changeOrigin: true, })); app.listen(5174, () => { console.log('Server running on port 5174...'); }); ``` 这种方法特别适合于需要频繁调用外部 API 的项目,因为它不仅解决了问题,还能够隐藏实际的目标 URL 地址。 --- #### 4. WebSocket 协议 WebSocket 是一种全双工通信协议,不受同源策略的影响,因此天然具备能力。如果应用场景涉及实时数据传输,则可以选择 WebSocket 来替代传统的 AJAX 请求。 客户端连接代码如下所示: ```javascript const socket = new WebSocket('ws://localhost:8080/socket'); socket.onopen = function() { console.log('Connection established.'); }; socket.onmessage = function(event) { console.log('Message from server:', event.data); }; ``` 相比传统方式,WebSocket 更加高效但也更复杂,需根据具体需求权衡利弊后再决定是否采用。 --- ### 总结 针对不同业务场景和技术栈,有多种手段可供选择以应对挑战。其中最常用也是最为灵活的方法莫过于启用 CORS 支持;而对于老旧环境或者特殊情况下则可能需要用到像 JSONP 这样的变通措施。当然还有诸如 Nginx 反向代理以及 WebSockets 等高级技巧也值得探索学习。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值