Flutter Web CORS解决方案1
本文介绍第一种解决FlutterWeb CORS问题的方案:修改Chrome浏览器安全策略或修改flutter web启动chrome代码。
设置CHROME_EXECUTABLE
参考 Disable Origin Policy CORS in Flutter web #46904 中的脚本方案(!!!#f9cb9c script solution !!!),通过设置环境变量 CHROME_EXECUTABLE
指定 chrome 启动脚本。
关于 CHROME_EXECUTABLE
Flutter checks this env variable before it launches Chrome. If you try to start
flutter run -d chrome
on a system that doesn’t have Chrome installed, Flutter will specifically ask you to either put it into the default location or to tell it where it is usingCHROME_EXECUTABLE
.
执行 flutter doctor 会检查 Chrome - develop for the web
这一项。
如果安装了 Google Chrome,正常会提示:
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
如果没有安装 Google Chrome,执行 flutter doctor 则提示没有设置环境变量 CHROME_EXECUTABLE
:
[✗] Chrome - develop for the web (Cannot find chrome executable at google-chrome)
! CHROME_EXECUTABLE not set
执行 flutter run -d chrome
命令可能会报以下错误:
Try setting CHROME_EXECUTABLE to a Chrome executable
基于以上提示,flutter run -d chrome
会检查 Google Chrome 默认安装目录,如果没有安装则尝试读取环境变量 CHROME_EXECUTABLE
查找 chrome 可执行路径,然后执行 CHROME_EXECUTABLE
启动独立的 Google Chrome 调试进程。
据此,我们可以定制 CHROME_EXECUTABLE
,启动 Google Chrome 时传递一些安全策略参数,实现禁止CORS检查的目标。
创建 CHROME_EXECUTABLE
- 创建脚本
/usr/local/etc/chrome/launch-unsafe.sh
,内容如下:
$ mkdir -p /usr/local/etc/chrome
$ vim /usr/local/etc/chrome/launch-unsafe.sh
#!/usr/bin/env bash
# 已存在不影响
mkdir -p /tmp/chrome_dev_test
# 末尾的 $* 或 $@ for macOS, %* for windows
# --disable-site-isolation-trials 参数可选
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/tmp/chrome_dev_test" --disable-web-security $@
也可事先执行
mkdir -p /tmp/chrome_dev_test
创建 chrome 调试目录。
-
执行
sudo chmod +x /usr/local/etc/chrome/launch-unsafe.sh
赋予脚本可执行权限。 -
在
~/.zshrc
中配置以下命令,导出CHROME_EXECUTABLE
变量:- 如果将脚本放置在
/Applications/Google\ Chrome.app/Contents/MacOS/
目录,则升级会被覆盖移除! - 如果后续调试想恢复 Chrome 正常的 CORS 安全策略,可以在
~/.zshrc
中注释掉这一句。
- 如果将脚本放置在
export CHROME_EXECUTABLE=/usr/local/etc/chrome/launch-unsafe.sh
- During development,
Chrome
(on macOS, Windows, and Linux) andEdge
(on Windows) are supported as the default browsers for debugging your app. - You can select
Chrome
orEdge
as the target device in Android Studio/IntelliJ and VS Code. - The device pulldown should now include the
Chrome (web)
option for all channels.
设置环境变量 CHROME_EXECUTABLE
后,重新执行 flutter doctor -v
,检测到 chrome 启动脚本:
[✓] Chrome - develop for the web
• CHROME_EXECUTABLE = /usr/local/etc/chrome/launch-unsafe.sh
执行 flutter devices
正常应列出 Chrome (web) • chrome:
$ flutter devices
1 connected device:
Chrome (web) • chrome • web-javascript • Google Chrome 97.0.4692.99
重新执行命令 flutter run -d chrome
启动调试,将按照 launch-unsafe.sh 中的命令启动独立的禁用了安全策略的 Chrome 浏览器进行调试。
- 如果是通过 vscode 或 Android Studio 调试,在
~/.zshrc
中添加或注释 export CHROME_EXECUTABLE 后,需要重启 IDE 生效。 - 新开启的 Chrome 调试进程,地址栏下会出现告警消息栏提示 “You are using an unsupported command-line flag: --disable-web-security. Stability and security will suffer.”。
关于 CHROME_EXECUTABLE
可参考以下:
-
Flutter No devices found with name or id matching ‘chrome’ on Windows 10
-
Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable. Flutter 2.0
-
How can I debug a Flutter Web App on Safari using the inspector?
# export CHROME_EXECUTABLE=/Applications/Safari.app/Contents/MacOS/Safari # 貌似无效?
export CHROME_EXECUTABLE="/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
export CHROME_EXECUTABLE="/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
修改 chrome.dart 禁用安全策略
修改 flutter SDK 中 web 调试的 chrome 调起脚本,在启动参数添加 --disable-web-security
禁用安全策略,也可解决协议访问跨域问题。
- cd flutter SDK directory:
cd $FVM_HOME/versions/beta
- Remove or rename(mv)
bin/cache/flutter_tools.stamp
- Modify(vim)
packages/flutter_tools/lib/src/web/chrome.dart
- Find and Comment
'--disable-extensions'
- Add
'--disable-web-security'
重新执行 flutter run -d chrome
或通过 vscode launch 方式启动调试,创建的独立 chrome 进程将忽略 CORS 错误检查。
升级 flutterSDK 后需重新修改
- flutterSDK 经过以上涂改之后,想要逆向修改貌似无法恢复。
- 若要升级 flutterSDK,执行
flutter upgrade
需带选项--force
强制更新,chrome.dart 的改动将被重置,需要重新修改一遍。
建议用 FVM 的某个版本(beta)专干此事,避免频繁修改 stable 版本!
升级后指定–web-hostname参数问题
11Oct21 更新:google-chrome 从 94.0.4606.71 升级为 94.0.4606.81 后,选项--web-hostname
指定参数 0.0.0.0 还是会报 CORS 错误。
flutter run -d chrome --web-hostname 0.0.0.0 --web-port 8080
不指定
--web-hostname
或指定具体 IP 10.68.59.70 则恢复正常!
后续更新 google-chrome,这个问题又不复存在,flutter run 选项 --web-hostname
指定参数 0.0.0.0 运行正常。
浏览器启用 Allow-CORS 插件
在桌面浏览器或安卓Kiwi浏览器通过IP链接( http://9.139.144.43/ )访问部署的flutterWeb产物,可在浏览器中安装Allow-CORS插件临时解决。
-
桌面端Google Chrome浏览器,安装启用 Allow CORS: Access-Control-Allow-Origin @chrome webstore 插件,可以访问
xxx.coding.net
域名下的协议。 -
安卓可安装 kiwi浏览器,然后在 chrome webstore 上搜索安装启用 Allow CORS: Access-Control-Allow-Origin 插件,也可以访问
xxx.coding.net
域名下的协议。
Moesif Origin
However, Chrome does support cross-origin requests from localhost. Make sure to add a header for Access-Control-Allow-Origin
for localhost
.
Allow CORS extension will add the necessary HTTP Headers for CORS:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: "GET, PUT, POST, DELETE, HEAD, OPTIONS"
Access-Control-Expose-Headers: <you can add values here>
在 Google Chrome 浏览器工具栏,点击 CORS 插件图标:
①:点击 Toggle ON|OFF
启用或禁用插件;
②:点击 Open options page
打开配置页面;
③:勾选 2. Access-Control-Allow-Headers
:
部分协议OPTIONS预检跨域问题
本地调试常规 Chrome 浏览器和安卓 Kiwi 浏览器启动默认未禁用安全策略,对于复杂请求(例如Content-Type字段的类型是 application/json
)将会在发起正式请求之前,先发起 OPTIONS
预检请求。
即使开启了 Allow-CORS 插件,有些协议的 OPTIONS 请求仍返回 500,导致不会继续发起 GET/POST 协议请求。
为什么会在GET或POST请求之前先进行一次OPTIONS请求?
在有很多情况下,当我们在js里面调用一次ajax请求时,在浏览器那边却会查询到两次请求。第一次的Request Method是
OPTIONS
,第二次才是真正的GET
或POST
请求。
查阅相关的资料之后发现,这是浏览器对复杂跨域请求的一种处理方式。在真正发送请求之前,会先进行一次Request Method为OPTIONS
的"预检"请求(preflight)。它的作用是用于试探服务器响应是否正确,即是否能接受真正的请求。如果OPTIONS
预检请求获取到的响应是拒绝性质的(例如返回状态码=500),那么就会停止第二次的真正请求。
从【我管理的】tab 点进流水线 test-artifacts
,拉取当前构建详情(lastrun)OPTIONS 预请求返回200。
继续正式拉取当前构建详情(lastrun),GET 请求返回200。
点击切换到构建物 tab,拉取构建物列表(artifacts)预请求OPTIONS提示 Provisional headers are shown
:
拉取构建物列表(artifacts)预请求OPTIONS返回 500
(Internal Server Error),将不再发起正式的 GET 请求。
解决方案:后台服务器同意放行拉取构建物列表(artifacts)的OPTIONS预检请求。