2013-04-16 295 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(); 
    }); 
相關問題