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 using CHROME_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

  1. 创建脚本 /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 调试目录。

  1. 执行 sudo chmod +x /usr/local/etc/chrome/launch-unsafe.sh 赋予脚本可执行权限。

  2. ~/.zshrc 中配置以下命令,导出 CHROME_EXECUTABLE 变量:

    • 如果将脚本放置在 /Applications/Google\ Chrome.app/Contents/MacOS/ 目录,则升级会被覆盖移除!
    • 如果后续调试想恢复 Chrome 正常的 CORS 安全策略,可以在 ~/.zshrc 中注释掉这一句。
export CHROME_EXECUTABLE=/usr/local/etc/chrome/launch-unsafe.sh

Web FAQ:

  • During development, Chrome (on macOS, Windows, and Linux) and Edge (on Windows) are supported as the default browsers for debugging your app.
  • You can select Chrome or Edge 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 浏览器进行调试。

  1. 如果是通过 vscode 或 Android Studio 调试,在 ~/.zshrc 中添加或注释 export CHROME_EXECUTABLE 后,需要重启 IDE 生效。
  2. 新开启的 Chrome 调试进程,地址栏下会出现告警消息栏提示 “You are using an unsupported command-line flag: --disable-web-security. Stability and security will suffer.”。

在这里插入图片描述


关于 CHROME_EXECUTABLE 可参考以下:

# 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 禁用安全策略,也可解决协议访问跨域问题。

  1. cd flutter SDK directory: cd $FVM_HOME/versions/beta
  2. Remove or rename(mv) bin/cache/flutter_tools.stamp
  3. 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 后需重新修改

  1. flutterSDK 经过以上涂改之后,想要逆向修改貌似无法恢复。
  2. 若要升级 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插件临时解决。

  1. 桌面端Google Chrome浏览器,安装启用 Allow CORS: Access-Control-Allow-Origin @chrome webstore 插件,可以访问 xxx.coding.net 域名下的协议。

  2. 安卓可安装 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,第二次才是真正的 GETPOST 请求。
查阅相关的资料之后发现,这是浏览器对复杂跨域请求的一种处理方式。在真正发送请求之前,会先进行一次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预检请求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值