【问题标题】:The 'Access-Control-Allow-Origin' header has a value 'http://localhost:4200' that is not equal to the supplied origin“Access-Control-Allow-Origin”标头的值“http://localhost:4200”不等于提供的来源
【发布时间】:2019-04-04 20:30:47
【问题描述】:

(标题中错误消息的继续)“因此不允许访问 Origin 'http://127.0.0.1:4200'。”

当使用同一个 API 时,我无法在两个不同的域上运行同一个 Angular 5 站点。

此错误消息来自 Chrome。 Firefox 中的错误是:

跨域请求被阻止:同源策略不允许读取位于http://myapitest.local/v1/subscription/current/products 的远程资源。 (原因:CORS 标头“Access-Control-Allow-Origin”与“http://127.0.0.1:4200”不匹配)

我在处理我们的 Angular 应用程序的白标版本时注意到了这一点,该应用程序将在我们常规应用程序的替代 URL 上运行,但仍使用在相同 URL 上运行的相同 Laravel api。我已向 Laravel 添加了适当的 CORS 配置,这似乎是浏览器问题 - 不知道如何解决。

例如,我通过将 localhost:4200 更改为 127.0.0.1:4200 在 localhost 重新创建了它。

奇怪的是,使用正确的 CORS 标头,预检似乎是成功的。

但是,在 GET 上,它似乎在响应中返回了 WRONG Access-Control-Allow-Origin 标头。

在此值得注意的是,将我在 API 中的 Allowed Origins 更改为允许所有 ('*') 并不能解决此问题。

我不确定我可以提供哪些其他信息或代码来更清楚地说明这一点。谢谢。

【问题讨论】:

  • 从 localhost:4200 和我们部署的站点从地理服务器访问地图图块时,我遇到了同样的问题。有时 ctrl-f5 会修复它,但并不总是在 chrome 中。我尝试在浏览器中从两个站点清除应用程序数据。你找到解决这个@QuietSeditionist 的方法了吗?
  • 通过在 chrome 开发工具的网络选项卡中临时禁用缓存来修复它。奇怪的,激进的缓存。

标签: angular laravel security cors


【解决方案1】:

将此添加到您的 public/index.php 文件中

header('Access-Control-Allow-Origin: *');

【讨论】:

  • 那么你必须把确切的路线允许原点
  • 我已经拥有了 Laravel API 中指定的所有可接受的来源。
  • 感谢您的 sn-p,它可能会提供一些有限的即时帮助。通过描述为什么这是解决问题的好方法,正确的解释将极大地改进其long-term value,并使其对有其他类似问题的未来读者更有用。请编辑您的答案以添加一些解释,包括您所做的假设。
【解决方案2】:

您可以为 Angular Webpack 开发服务器提供的请求设置代理。通过使用代理,您可以将后端 URL 更改为源自 Angular 域托管 URL。这将通过您的服务命令或 package.json 中的 --proxy-config 来实现。这样 Angular 将在具有相同后端服务的不同 URl 中运行。

在 package.json 附近添加一个名为 proxy.conf.json 的文件。从您的请求获取 URL 添加 /proxy

在你的 proxy.conf 文件中添加这个

{
  "/proxy": {
  "target": "http://localhost:3000",
  "secure": false,
  "pathRewrite": {
  "^/proxy": ""
 }
}

将你的服务命令更改为

ng serve --proxy-config proxy.conf.json --port 4200 --host 0.0.0.0

在您的 angular.json 中更改服务目标

"architect": {
    "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
    "browserTarget": "your-application-name:build",
    "proxyConfig": "proxy.conf.json"
 },

注意:确保在您的 Http 服务 URL 和代理配置中添加 /proxy 仅用于开发目的

对于生产环境你应该在 webservers 中配置。

【讨论】:

  • 感谢@esakki 的明显努力,但您能帮我理解一下吗:1) 设置代理的目的是什么? 2)如何在部署中配置它?
  • CORS 错误发生在您的请求是从一个域到域外或不同端口的情况下。从代理传递您的后端 API 调用 URL 将被修改为请求源域 ex 的替换; [localhost:8080/profile/rootData]修改为[localhost:4200/proxy/profile/rootData]
  • 对于部署,您可以使用 mod_proxy 在您的 Web 服务器中为 apache 配置 :80> ServerName localhost DocumentRoot /var/www/html/dist ProxyPass /proxy/ @987654323 @ProxyPassReverse /proxy/* localhost:8080
【解决方案3】:

我认为您使用 web.php 这条路线 在文件的顶部,请使用它并尝试

 <?php
  header('Access-Control-Allow-Origin: *');
  header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
  header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CSRF-Token");

Route::get('/login', 'Auth\LoginController@showLoginForm');

【讨论】:

  • 1) 我正在使用 Laravel,所以这不适用。 2) 我已经说过我不希望允许从所有来源访问 API,包括 '*' 也不能解决问题。 -- 你认为这将如何解决我的问题??
【解决方案4】:

假设您的 api 在 8080 上运行,而您的 Angular 代码在 4200 上运行。

在您的 Angular 应用程序中创建一个名为 proxy.conf.json 的文件

{
    "/api/": {
        "target": "http://localhost:8080/",
        "secure": false,
        "changeOrigin": true
    }
}

使用此命令启动 Angular 应用程序

ng serve --port 4200 --proxy-config proxy.conf.json

使用此配置,当您调用 localhost:4200/api 时,它将调用 8080,并且不会出现任何 CORS 错误

【讨论】:

  • 这将不允许跨域进行测试,并且会删除所有安全性。
  • 这种方法如何应用于生产环境?
  • @QuietSeditionist 在 ng build --prod 之后,您可以在生产中使用后端服务。当两个本地应用程序需要相互通信时,这解决了本地开发问题。如果您特别想使用 ng serve ,您可以创建特定于环境的另一个文件,例如 proxy.conf.prod.json 并使用该文件调用 ng serve 。
【解决方案5】:

设置反向代理服务器并为两个域配置路径。
Nginx Guide

这将允许您通过http://localhost/访问所有内容
让我们假设:
A -> Angular 应用程序 (localhost:4200)
B -> 你的其他域 API (myapitest.local)

示例流程:
- 浏览器请求(http://localhost/angular) -> Nginx -> A
- 从后端加载数据 -> Nginx -> B

因此,在 Nginx 的帮助下,您将能够从 http://localhost/ 访问“A” 和“B”也来自http://localhost/
由于来源相同,所以不会出现 CORS 错误。

【讨论】:

    【解决方案6】:

    问题出在名称映射中。由于一个服务器池可能有多个 IP 地址,因此大多数浏览器会将 IP 地址映射到一个名称。这通常通过请求的 DNS 名称完成。在你的情况下没有名字,所以它正在寻找 在主机文件(Linux 上的 /etc/hosts 或 Windows 上的 C:\Windows\System32\Drivers\etc\Hosts)中设置 IP 地址并从那里返回名称。

    由于您需要跨域进行测试(充当 2 个单独的服务器),请在主机文件中添加一行,将 myapitest.local 指向 127.0.0.2 。还有一行 myapitest2.local 到 127.0.0.3 。这将允许您的本地命名与 IP 地址相匹配,并通过适当的配置(为每个服务器实例指定要绑定的特定侦听地址),然后每个服务器实例都可以在端口 80 上运行。

    在所有跨域请求和授权中使用名称。

    编辑

    由于Access-Control-Allow-Credentials: true,通配符不起作用。

    在 dev-api.ourdomain.com 服务器上: 将 Response Header 添加到路由文件 Routes/api.php 中,该文件为已批准的域构建 Access-Control-Allow-Origin: 标头。您也可以将其用作中间件,但为简单起见,我将使用简单的路由进行演示。预检路线也必须这样做。

    Route::get('/method/{id}', function (Request $request, $id) {
        $retval = method($id);
        $origin_allowed = $request->header('HTTP_ORIGIN');
        $allowed = array("dev.ourdomain.com", "dev.alternatedomain.com");
        if(in_array($origin_domain, $allowed))
            return ($retval)->header('Access-Control-Allow-Origin:',$origin_domain);
        else 
            return "Unauthorized";
    });
    

    这只是演示概念的示例代码。

    确保在注销时清除 HTTP 授权和 csrf 令牌。

    【讨论】:

    • 本方案不使用代理,可以模拟生产环境。
    • 这如何应用于部署环境?当我第一次发现这个问题时,它是在我们的集成环境中,当我通过(例如)dev.ourdomain.com 访问应用程序时遇到问题,然后尝试注销并登录到白标版本的dev.alternatedomain.com 上的应用程序。这两个都通过同一个 URL dev-api.ourdomain.com 访问 api。
    • @QuietSeditionist,我觉得我要么错过了问题,要么错过了最后一条评论。如果您能更清楚地了解您正在寻找的结果,那将会很有帮助。
    • Laravel 负责这一切。我只配置了允许的来源,这就完成了。当 Chrome 甚至拒绝根据之前调用的缓存(显然)原始标头对 API 进行调用时,就会出现问题。
    【解决方案7】:

    您可能已经安装了 HTTPS Everywhere 扩展。确保在 Localhost 上禁用 HTTPS Everywhere。这就是造成我这个问题的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-30
      • 2016-10-28
      • 2017-08-24
      • 2013-04-09
      • 2012-09-22
      • 1970-01-01
      • 2016-08-06
      相关资源
      最近更新 更多