如何仅使用 dart 代码解决 flutter web api cors 错误?

How to solve flutter web api cors error only with dart code?

CORS 错误似乎是网络领域的 well-known 问题。但是我第一次尝试 flutter web 时遇到了严重错误。

下面的代码在 运行 在 iOS 设备上时在应用程序版本中运行良好,但是当我在 Chrome 上测试相同的代码并从 beta 通道进行网络调试时,它遇到 CORS 错误。

其他 Whosebug 答案解释了如何解决他们项目的服务器端文件的 CORS 问题。但我完全不知道什么是服务器,也不知道如何处理他们的回答。来自 Chrome 控制台的错误消息低于

[从源 'http://localhost:52700' 访问位于 'https://kapi.kakao.com/v1/payment/ready' 的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:否 'Access-Control-Allow-Origin' header 出现在请求的资源上。 ]

所以,我想做的是仅使用 DART 代码解决上述 'Access-Control-Allow-Origin header' 问题!下面的代码是我试图用 main.dart.

解决这些问题的方法
onPressed: () async {
      var res =
          await http.post('https://kapi.kakao.com/v1/payment/ready', encoding: Encoding.getByName('utf8'), headers: {
        'Authorization': 'KakaoAK $_ADMIN_KEY',
        HttpHeaders.authorizationHeader: 'KakaoAK $_ADMIN_KEY',
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, HEAD",
      }, body: {
        'cid': 'TC0ONETIME',
        'partner_order_id': 'partner_order_id',
        'partner_user_id': 'partner_user_id',
        'item_name': 'cool_beer',
        'quantity': '1',
        'total_amount': '22222',
        'vat_amount': '2222',
        'tax_free_amount': '0',
        'approval_url': '$_URL/kakaopayment',
        'fail_url': '$_URL/kakaopayment',
        'cancel_url': '$_URL/kakaopayment'
      });
      Map<String, dynamic> result = json.decode(res.body);
      print(result);
    },

尽管我实际上有大多数其他答案推荐的 header "Access-Control-Allow-Origin": "*",但 Chrome 控制台打印了相同的错误消息。奇怪的是,相同的代码在 mobileApp 版本中发出了成功的请求。所以我认为这只是 flutter WEB 版本的问题。

希望有人能解决并建议 only-dart 代码来解决我 main.dart 中的问题!!感谢您阅读 [:

我认为你这样做的方式可能不对。 cors headers 应该添加到 HTTP 响应 header 中,而你显然在 reuqest header 中添加了它们。

有关详细信息,请查看文档 https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#what_requests_use_cors

1- 转到 flutter\bin\cache 并删除名为:flutter_tools.stamp

的文件

2- 转到 flutter\packages\flutter_tools\lib\src\web 并打开文件 chrome.dart

3- 查找'--disable-extensions'

4- 添加 '--disable-web-security'

真正需要像 node js 或 django 这样的服务器端引擎来使用带有一堆外部 apis 的 flutter web。实际上,由于与端口号差异相关的 CORS 机制,当我们尝试使用内部 api 时,很可能出现相同的 CORS 错误。

来自 SO 贡献者的大量步骤和答案建议使用 chrome 扩展来避免 CORS 错误,但这实际上对用户来说并不酷。所有用户都应下载浏览器扩展以使用我们提供的单一网站,如果我们使用真正的服务器引擎,则不会存在。

据我所知,CORS 来自浏览器,因此我们具有相同 api 代码的 flutter ios 和 android 应用程序不会出现这些 CORS 错误。我第一次在 flutter web 中遇到这个错误,我相信我可以在我的应用程序代码行中处理 CORS。但这对用户和长期开发计划来说实际上不是健康的方式。

希望所有 flutter web 新手都明白 web 对我们来说是一个相当狂野的领域。尽管我在这里也是新手,但我强烈推荐 1.22.n 中的所有 flutter web 开发人员,以稳定地学习节点 js 等服务器端引擎。值得一试。

如果您一直到我的自我回答的这一行,这里有一个使用节点 js 的 flutter web 的简单指南。 Flutter web 处于稳定状态,但所有必要的基础设施还没有为像我这样的新手准备好。所以当你第一次涉足 web 领域时要小心,并希望你重新检查所有条件和要求,以确定你是否真的需要你的 flutter 应用程序的 web 版本,以及你是否真的需要用 flutter 来完成这项工作。我的回答是肯定的哈哈

https://blog.logrocket.com/flutter-web-app-node-js/

如果您 运行 Spring 引导服务器,请将“@CrossOrigin”添加到您的控制器或您的服务方法。

@CrossOrigin
@PostMapping(path="/upload")
public @ResponseBody ResponseEntity<Void> upload(@RequestBody Object object) {
    // ...
}

我知道这个问题明确要求仅“使用 dart 代码”的解决方案,但我无法使用 dart 代码修复异常(例如通过更改 header)。

1- 转到 flutter\bin\cache 并删除名为:flutter_tools.stamp

的文件

2- 转到 flutter\packages\flutter_tools\lib\src\web 并打开文件 chrome.dart。

3- 查找“--disable-extensions”

4- 添加“--disable-web-security”

5- 添加'--user-data-dir=/Users/mt/Desktop/chromedata'

更新

我推荐使用。他的封装使得修改Flutter源码非常方便


MacOS 和 Android Studio 的替代解决方案(不修改 Flutter 源)

我们使用与 Osman Tuzcu 类似的方法。我们没有修改 Flutter 源代码,而是在 shell 脚本中添加了 --disable-web-security 参数,并且只转发了 Flutter 设置的所有其他参数。它可能看起来过于复杂,但只需一分钟,无需为每个 Flutter 版本重复。

1。 运行 这个在你的终端里

echo '#!/bin/zsh
# See also 
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
set -e ; /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --test-type --disable-web-security "$@" ; set +e &
PID=$!
wait $PID
trap - SIGINT SIGTERM EXIT
wait $PID
' > ~/chrome_launcher

chmod 755 ~/chrome_launcher

这会向您的用户文件夹添加一个 chrome_launcher 脚本并将其标记为可执行文件。

2。将此行添加到您的 .zshrc(或 .bashrc 等):

export CHROME_EXECUTABLE=~/chrome_launcher

3。重新启动 Android Studio

如果简单的重启不起作用,请使用 Android Studio 中的 无效缓存/重启 强制加载更改。

备注

该脚本还添加了 --test-type 标志来抑制有关已禁用安全功能的丑陋警告。请注意,此选项也可能会抑制其他错误消息! CHROME_EXECUTABLE 仅采用可执行文件的路径,无法在那里设置参数。 在不捕获退出信号并终止进程组的情况下,当您在 Android Studio 中点击 停止按钮 时,Google Chrome 实例不会被终止。

使用 Osman Tuzcu's answer, I created flutter_cors 可以简化流程。

run/compile 您的 Flutter 网络项目使用 web-renderer。这应该可以解决本地和远程问题:

flutter run -d chrome --web-renderer html
flutter build web --web-renderer html

https://docs.flutter.dev/development/platform-integration/web-images

flutter run -d chrome --web-renderer html
flutter build web --web-renderer html

此官方解决方案仅适用于 Chrome (Source)。但我每次都必须先运行。

flutter run -d chrome --web-renderer html

并且禁用网络安全也有效 ()。但是浏览器会显示一个警告横幅。

但如果您运行使用的浏览器不同于Chrome(例如Edge)并且您希望保留'web security'启用。 您可以在 VS Code 的设置中更改默认 Web 渲染器

File ==> Preferences ==> Settings ==> Enter 'Flutter Web' in the Search Bar ==> Set the default web renderer to html

我认为按照建议禁用网络安全将使您暂时跳过当前错误,但是当您在其他设备上进行生产或测试时,问题将仍然存在,因为它只是一种解决方法,正确的解决方案来自服务器端允许来自请求域的 CORS 并允许所需的方法和凭据(如果需要)。

禁用网络安全的方法在开发中效果很好,但在生产中可能不太好。在生产 dart 代码中对我有用的一种方法涉及通过保持 Web 请求简单来完全避免 pre-flight CORS 检查。在我的例子中,这意味着将请求 header 更改为包含:

'Content-Type': 'text/plain'

即使我实际上发送的是 json,但将其设置为 text/plain 可避免 pre-flight CORS 检查。我调用的 lambda 函数不支持 pre-flight OPTIONS 请求。

这里有一些关于 keep a request simple 和避免 pre-flight 请求

的其他方法的信息