【问题标题】:Origin http://localhost is not allowed by Access-Control-Allow-OriginAccess-Control-Allow-Origin 不允许来源 http://localhost
【发布时间】:2013-04-09 09:47:44
【问题描述】:

我正在尝试从backbone.js 获取到我的node.js 服务器。但是,我在控制台中收到以下错误:

Origin http://localhost is not allowed by Access-Control-Allow-Origin.

我将以下内容添加到我的 node.js 服务器:

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', "http://localhost");
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
};

app.configure(function() {
    app.use(allowCrossDomain);
});

但它仍然返回相同的错误。但是,即使这确实有效,它似乎也不是理想的解决方案,因为我希望来自世界各地的用户都能够发送请求。

【问题讨论】:

标签: javascript node.js backbone.js cors


【解决方案1】:

如果您希望每个人都能访问 Node 应用程序,请尝试使用

res.header('Access-Control-Allow-Origin', "*")

这将允许来自任何来源的请求。 CORS enable 站点有很多关于不同 Access-Control-Allow 标头以及如何使用它们的信息。

我使用的是 Chrome,请查看 this 关于 localhost 和 Access-Control-Allow-Origin 的 bug。还有一个StackOverflow question here 详细说明了这个问题。

【讨论】:

  • 这是一种安全的方法吗?我发现this 涉及节点、骨干网和跨域的东西。它可以工作,但每隔一段时间它会抛出一个 404,我认为这可能与 chrome 错误有关。
  • 将此方法称为“安全”会产生误导,但是我以前在每个 AJAX 请求都带有自己的身份验证令牌的情况下使用过它。 CORS 旨在防止恶意人员欺骗您的用户浏览器从您的应用程序访问敏感信息。理想情况下,您应该为您的主干应用程序可以从中提供服务的每个可能的合法位置添加一个标头。
  • 如果我使用 3rd Party API 怎么办?我无法在他们的服务器上添加“允许访问”。您正在展示本地项目的示例。我有同样的问题,但我的请求是转到另一个网站 url。如何解决它的任何想法?
  • CORS 专为防止您尝试做的事情而设计 :) 在某些情况下存在安全隐患。您可以做的是为 3rd 方 API 构建代理。您的 webapp 查询您的代理,并且您的代理调用 3rd 方 API。现在您可以控制代理上的标头,并且允许您的代理调用 3rd 方 API。
【解决方案2】:

如果您正在对您的 localhost 进行 fetch 调用,我猜它是由 node.js 在与您的主干代码相同的目录中运行的,那么它很可能在http://localhost:3000 或类似的地方。这应该是你的模型:

var model = Backbone.Model.extend({
    url: '/item'
});

在你的 node.js 中你现在必须像这样接受这个调用:

app.get('/item', function(req, res){
    res.send('some info here');
});

【讨论】:

    【解决方案3】:

    有 2 个调用需要设置正确的标头。最初有一个预检检查,所以你需要类似...

    app.get('/item', item.list);
    app.options('/item', item.preflight);
    

    然后有以下功能...

    exports.list = function (req, res) {
    Items.allItems(function (err, items) {
        ...
            res.header('Access-Control-Allow-Origin', "*");     // TODO - Make this more secure!!
            res.header('Access-Control-Allow-Methods', 'GET,PUT,POST');
            res.header('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept');
            res.send(items);
          }
       );
    };
    

    飞行前检查

    exports.preflight = function (req, res) {
    Items.allItems(function (err, items) {
            res.header('Access-Control-Allow-Origin', "*");     // TODO - Make this more secure!!
            res.header('Access-Control-Allow-Methods', 'GET,PUT,POST');
            res.header('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept');
            res.send(200);
        }
      );
    };
    

    如果需要,您可以将 res.header() 代码合并到一个函数中。

    也如上所述,小心使用 res.header('Access-Control-Allow-Origin', "*") 这意味着任何人都可以访问您的网站!

    【讨论】:

      【解决方案4】:

      通过 localhost,您必须使用 null 来源。我建议您创建一个允许的主机列表并检查请求的 Host 标头。如果它包含在列表中,则通过 localhost 发回一个

      res.header('Access-Control-Allow-Origin', "null");
      

      任何其他域名

      res.header('Access-Control-Allow-Origin', hostSentByTheRequestHeader);
      

      如果列表中不包含它,则发回服务器主机名,因此浏览器将隐藏这些请求的响应。

      这更加安全,因为通过允许来源 * 和允许凭据,每个人都可以例如窃取登录用户的个人资料数据等...

      所以总结如下:

      if (reqHost in allowedHosts)
          if (reqHost == "http://localhost")
              res.header('Access-Control-Allow-Origin', "null");
          else
              res.header('Access-Control-Allow-Origin', reqHost);
      else
          res.header('Access-Control-Allow-Origin', serverHost);
      

      如果您想允许多个其他域访问您的页面,这是最安全的解决方案。 (我猜你可以通过node.js弄清楚如何获取主机请求头和服务器主机。)

      【讨论】:

        【解决方案5】:

        这种方法解决了我的问题,允许多个域

        app.use(function(req, res, next) {
              var allowedOrigins = ['http://127.0.0.1:8020', 'http://localhost:8020', 'http://127.0.0.1:9000', 'http://localhost:9000'];
              var origin = req.headers.origin;
              if(allowedOrigins.indexOf(origin) > -1){
                   res.setHeader('Access-Control-Allow-Origin', origin);
              }
              //res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:8020');
              res.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
              res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
              res.header('Access-Control-Allow-Credentials', true);
              return next();
            });
        

        【讨论】:

          猜你喜欢
          • 2012-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-14
          • 2012-12-28
          • 2013-07-20
          • 2012-11-04
          相关资源
          最近更新 更多