2013-04-16 246 views
8

我试图从backbone.js对我的node.js服务器执行提取操作。不过,我得到以下错误在控制台:访问控制 - 允许来源不允许来源http:// localhost

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); 
}); 

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

+0

您可能需要使用“* '而不是http:// localhost。然而,我并不熟悉Node,所以我不知道这是答案,还是它的配置问题。 – ryanday

+0

看看这是否有帮助http://stackoverflow.com/questions/15534640/ajax-origin-localhost-is-not-allowed-by-access-control-allow-origin/15537999#15537999 – PSL

+0

@generalhenry你错了。 ['http:// localhost'是正确的](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS),你应该删除你的评论以避免混淆。 – DanFromGermany

回答

11

如果你希望每个人都能够访问节点的应用程序,然后尝试使用

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

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

我正在使用Chrome浏览器,请查看this关于本地主机和Access-Control-Allow-Origin的bug错误。还有另外一个StackOverflow question here详细说明了这个问题。

+0

这是一个安全的方法吗?我发现[this](https://github.com/thomasdavis/backbonetutorials/blob/gh-pages/examples/cross-domain/server.js)关于节点,主干和跨域的内容。它有效,但每隔一段时间它会抛出一个404,我认为这可能与铬错误有关。 –

+1

将这种方法称为“安全”会引起误解,但是在每个AJAX请求携带自己的身份验证令牌的情况下,我都会使用它。 CORS旨在防止恶意的人欺骗用户的浏览器访问应用程序中的敏感信息。理想情况下,您应该为每个可能的合法位置添加一个标题,以供您的骨干应用程序使用。 – ryanday

+0

非常感谢您的帮助! –

0

如果你正在抓取打电话到localhost,我猜是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'); 
}); 
0

有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',“*”) 这意味着任何人都可以访问您的网站!

0

由localhost你必须使用null的由来。我建议您创建一个允许的主机列表并检查请求的标头Host。如果它是由清单载,然后通过本地主机被其他域的

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

如果不是由列表包含,然后发送回服务器的主机名发回的

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

,所以浏览器会隐藏这些请求的回应。

这是更安全,因为允许起源*,让大家的凭证将能够例如窃取的登录用户配置文件数据,等等

所以总结是这样的:

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中的服务器主机)

0

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

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(); 
    }); 
相关问题