Flutter Web 跨域(CORS)问题(chatgpt总结)
1. 什么是 Web 跨域?
在 Web 中,浏览器存在一套安全机制:
同源策略(Same-Origin Policy)
它规定:一个网页默认不能随意读取另一个不同 Origin 的资源。
一个 Origin 由三个部分组成:
协议 + 域名 + 端口
例如:
http://localhost:8080
│ │ │
协议 域名 端口
以下情况都属于不同 Origin:
http://example.com
https://example.com
协议不同。
https://example.com
https://api.example.com
域名不同。
https://example.com:8080
https://example.com:9000
端口不同。
2. 为什么浏览器要限制跨域?
主要是为了安全。
例如用户已经登录了:
https://bank.com
浏览器中可能保存着银行网站的 Cookie。
如果任何网站都可以随便读取银行的数据,那么恶意网站:
https://evil.com
就可能尝试读取:
https://bank.com/account
所以浏览器默认限制:
evil.com
│
└──────→ bank.com
❌
这就是同源策略。
3. 什么是 CORS?
CORS:
Cross-Origin Resource Sharing
跨源资源共享
它是浏览器提供的一种机制,让服务器可以明确告诉浏览器:
“我允许某个 Origin 的网页访问我的资源。”
例如 Flutter Web:
http://localhost:8080
请求:
https://api.example.com/user
服务器可以返回:
Access-Control-Allow-Origin: http://localhost:8080
浏览器看到以后,就允许网页读取响应。
4. Flutter Web 为什么会遇到 CORS?
Flutter 本身不是 CORS 的核心问题。
关键在于:
Flutter Web 最终运行在浏览器中。
例如使用 Dio:
final dio = Dio();
final response = await dio.get(
'https://api.example.com/user',
);
在 Android 中:
Flutter
↓
Dio
↓
网络
↓
API
一般不会受到浏览器 CORS 的限制。
但是 Flutter Web:
Flutter
↓
Dio
↓
浏览器 Chrome
↓
API
Chrome 会执行浏览器的同源策略和 CORS 检查。
所以:
Flutter Web + Dio
↓
Chrome
↓
CORS检查
↓
┌────┴────┐
↓ ↓
允许 不允许
↓ ↓
✅ ❌
5. Dio 会不会出现跨域问题?
会。
Dio 本身不能绕过浏览器 CORS。
例如:
final response = await dio.get(
'https://api.example.com/test',
);
如果 API 没有正确配置 CORS:
Chrome Console 可能出现:
Access to XMLHttpRequest at
'https://api.example.com/test'
from origin
'http://localhost:xxxxx'
has been blocked by CORS policy
Dio 可能表现为:
DioExceptionType.connectionError
或者:
XMLHttpRequest error.
所以:
Dio 能发请求 ≠ 浏览器一定允许读取这个请求的结果。
6. 如何判断是不是 CORS?
首先打开:
F12
→ Console
如果看到:
blocked by CORS policy
基本就可以确定是 CORS 问题。
典型错误:
Access to XMLHttpRequest at 'https://xxx.com/api'
from origin 'http://localhost:xxxxx'
has been blocked by CORS policy
而 Dio 代码中可能只看到:
DioException [connection error]
XMLHttpRequest error
因此:
判断 Flutter Web CORS 问题时,Chrome Console 比 Dio 的异常信息更重要。
7. 为什么有些 API 可以正常访问?
因为服务器已经配置了 CORS。
例如:
Access-Control-Allow-Origin: *
表示允许跨 Origin 访问。
所以:
Flutter Web
↓
Dio
↓
API
↓
Access-Control-Allow-Origin: *
↓
Chrome
↓
✅ 200
例如测试:
final response = await dio.get(
'https://jsonplaceholder.typicode.com/posts/1',
);
如果得到:
200
并不代表 Flutter Web 没有 CORS。
只是说明:
这个 API 允许当前请求跨域访问。
8. Postman 为什么可以请求,而浏览器不行?
这是一个很常见的误区。
例如:
Flutter Web → API
出现:
❌ CORS
但是:
Postman → API
得到:
✅ 200
这并不矛盾。
因为:
Postman
↓
API
不是网页浏览器环境。
而:
Flutter Web
↓
Chrome
↓
API
需要遵守浏览器的同源策略。
所以:
Postman 能请求 ≠ 浏览器能请求。
9. 临时解决方法:关闭 Chrome Web Security
开发 Flutter Web 时,可以使用:
--disable-web-security
让 Chrome 关闭 Web Security,从而绕过浏览器的 CORS 检查。
一种修改 Flutter SDK 的方法:
① 修改 chrome.dart
找到:
flutter/packages/flutter_tools/lib/src/web/chrome.dart
在 Chrome 启动参数的位置添加:
'--disable-web-security',
② 删除 Flutter 缓存
删除:
flutter/bin/cache/flutter_tools.snapshot
flutter/bin/cache/flutter_tools.stamp
③ 重新生成 Flutter Tools
执行:
flutter doctor -v
然后重新运行:
flutter run -d chrome
这样 Flutter 启动 Chrome 时,就会带上:
--disable-web-security
从而可以用于测试一些没有正确配置 CORS 的 API。
10. ⚠️ –disable-web-security 的注意事项
这个方法本质上是在告诉 Chrome:
关闭浏览器的 Web 安全限制。
因此它适合:
开发环境
测试
临时调试 CORS
不适合:
生产环境
正式部署的网站
因为这不是在真正解决 CORS。
正确的生产环境解决方案应该是:
Flutter Web
↓
API
↓
服务器配置 CORS
↓
Access-Control-Allow-Origin
↓
Chrome
↓
✅
而不是:
Flutter Web
↓
关闭 Chrome 安全策略
↓
API
↓
✅
11. 正规解决方案
如果 Flutter Web:
http://localhost:8080
访问:
https://api.example.com
那么后端应该允许:
Access-Control-Allow-Origin: http://localhost:8080
生产环境则应该根据实际域名配置,例如:
Access-Control-Allow-Origin: https://example.com
也可以根据后端框架配置 CORS。
12. VPN 和 CORS 没有直接关系
VPN:
改变网络连接方式、路由、出口 IP 等。
CORS:
浏览器控制网页是否可以读取其他 Origin 的资源。
所以:
VPN 开启
+
API 没有 CORS
=
❌ 仍然可能 CORS
而:
VPN 关闭
+
API 正确配置 CORS
=
✅ 正常访问
因此:
VPN 不会自动解决 CORS。
13. Flutter Web + Dio 的完整关系
可以记住这个流程:
Flutter Web
│
▼
Dio
│
▼
Chrome
│
同源策略 / CORS
│
┌───────┴───────┐
│ │
服务器允许 服务器不允许
│ │
▼ ▼
✅ ❌
200 CORS Error
14. 最重要的几个结论
① CORS 主要是浏览器的问题
不是 Dio 独有的问题,也不是 Flutter 独有的问题。
② Flutter Web 才特别容易遇到
因为 Flutter Web 运行在浏览器中。
③ Dio 不能绕过 CORS
Dio 只是 HTTP 客户端。
④ API 是否允许跨域由服务器配置
常见响应头:
Access-Control-Allow-Origin
⑤ Postman 能请求不代表浏览器能请求
因为 Postman 不受浏览器同源策略限制。
⑥ VPN 和 CORS 没有直接关系
VPN 不会自动解决跨域。
⑦ --disable-web-security 可以临时测试
Flutter 可以修改:
flutter/packages/flutter_tools/lib/src/web/chrome.dart
添加:
'--disable-web-security',
然后删除:
flutter/bin/cache/flutter_tools.snapshot
flutter/bin/cache/flutter_tools.stamp
执行:
flutter doctor -v
再:
flutter run -d chrome
但这只是开发调试方案。
一句话记忆
Flutter Web 使用 Dio 请求 API 时,Dio 负责发请求,Chrome 负责执行浏览器安全策略,服务器通过 CORS Header 告诉 Chrome“哪些网页可以读取我的响应”。
所以遇到:
blocked by CORS policy
第一反应应该是:
F12 → Console
↓
确认 CORS
↓
检查服务器 CORS 配置
而不是首先修改 Flutter。


评论区