2012-01-06 25 views
14

我正在開發一款小型多人遊戲。我想介紹身份驗證。我使用Node.js和Socket.io。套接字建立後的socket.io身份驗證

當用戶到達主頁面 - 我希望他們加入遊戲時,無論他們是否登錄 - 但他們將無法做任何事情(只有看)。

我怎麼才能在已經打開的套接字上認證用戶呢?

如果他們離開該網站並返回,我可以保持身份驗證嗎?你可以通過網絡套接字傳遞cookie嗎?

編輯

繼續我的問題。我有一個可能的想法是提供websocket連接,然後當他們嘗試登錄時,它將用戶名和密碼作爲消息傳遞給websocket。

client.on('onLogin', loginfunction); 

然後我可以採取用戶名和密碼,檢查對數據庫,然後採取插座的會話ID,並通過它的地方說會話身份驗證的用戶。

這種產品是否安全?我還可以在套接字上實現一個cookie,以便它們可以回來嗎? socket.io中有沒有什麼辦法說明套接字現在已經通過身份驗證,而不是手動檢查接收到的每條消息?

乾杯

+0

有沒有辦法或許是設置連接爲socket.io內認證的連接已經建立後握手完成的?用戶可以在準備好現有連接時提供登錄詳細信息,服務器可以驗證並返回唯一的會話ID。然後,客戶端JavaScript可以保存一個cookie以供將來使用。 – 2012-01-06 10:49:31

+0

查看[本文](http://www.danielbaulig.de/socket-ioexpress/)瞭解如何驗證socket.io會話。 – fent 2012-01-06 10:15:16

+0

是的,我已經看過那篇文章了。雖然我很高興設置cookie,但如果套接字已打開,則不允許在同一頁面上登錄。據推測,如果用戶禁用了Cookie,它也會受到影響嗎? – 2012-01-06 10:33:56

回答

5

這其實不是太難,但你接近了錯誤的方式。幾件事情:

  1. 不能設置與socket.io一個cookie;但是,您可以隨時獲取任何已連接的客戶端的Cookie值。爲了設置一個cookie,你將不得不發送一個新的http響應,這意味着用戶必須首先發送一個新的http請求(又名刷新或進入一個新頁面,這聽起來在這裏不可能)。

  2. 是的:socket.io是安全的(就傳輸的數據而言)。

因此,您可以執行以下操作:

在用戶的初始連接,創造了一個獨特的會話ID,如快遞的會議中間件生成的一個cookie。您需要將它們配置爲不會在會話結束時過期(否則只要關閉瀏覽器就會過期)。

接下來,您應該創建一個對象來存儲Cookie會話ID。每次設置一個新的connect.sid cookie時,將默認值爲false(意味着用戶已通過會話驗證,但不通過登錄驗證)存儲在您的新對象中

在用戶的登錄名上,發送一個套接字發送到服務器,然後在那裏您可以驗證登錄憑證,然後更新您創建的會話id對象以讀取當前套接字ID的真(登錄)。

現在,當收到一個新的http請求時,請閱讀cookie.sid,並檢查它的值是否爲true。

它應該看起來像下面這樣:

var express = require('express'), 
http = require('http'), 
cookie = require('cookie'); 

var app = express(); 
var server = http.createServer(app); 
var io = require('socket.io').listen(server); 


app.use(express.cookieParser()); 
app.use(express.session({ 
    secret: 'secret_pw', 
    store: sessionStore, 
    cookie: { 
     secure: true, 
     expires: new Date(Date.now() + 60 * 1000), //setting cookie to not expire on session end 
     maxAge: 60 * 1000, 
     key: 'connect.sid' 
    } 
})); 

var sessionobj = {}; //This is important; it will contain your connect.sid IDs. 

//io.set('authorization'...etc. here to authorize socket connection and ensure legitimacy 


app.get("/*", function(req, res, next){ 
    if(sessionobj[req.cookies['connect.sid']]){ 
     if(sessionobj[req.cookies['connect.sid']].login == true){ 
      //Authenticated AND Logged in 
     } 
     else{ 
      //authenticated but not logged in 
     } 
    } 
    else{ 
     //not authenticated 
    } 

}); 


io.sockets.on('connection', function(socket){ 
    sessionobj[cookie.parse(socket.handshake.headers.cookie)['connect.sid'].login = false; 
    sessionobj[cookie.parse(socket.handshake.headers.cookie)['connect.sid'].socketid = socket.id; 

    socket.on('login', function(data){ 
     //DB Call, where you authenticate login 
     //on callback (if login is successful): 
     sessionobj[cookie.parse(socket.handshake.headers.cookie)['connect.sid']] = true; 
    }); 

    socket.on('disconnect', function(data){ 
     //any cleanup actions you may want 
    }); 

}); 
+0

糾正我,如果我錯了,但不會永遠不會過期的會話通常被認爲是不安全 – brthornbury 2013-12-18 03:25:00

+0

@Mozoby我的代碼是設置Cookie過了一段時間後過期 - 它不是無限期的。我這樣做是因爲原來的問題似乎表明返回的用戶應該仍然登錄,這意味着我不能像在默認情況下一樣將瀏覽器關閉的cookie過期。 – Ari 2013-12-18 04:08:17

2

克里斯,我不能回答,因爲我不是socket.io的專家,但我可以也許嘗試把你指向另一個方向,可以幫助你 - 帶走一些開發時間。

但首先,免責聲明:我爲Realtime.co工作,並沒有嘗試做任何形式的廣告。我與開發人員密切合作,我只是想通過爲您的問題提供開箱即用的解決方案來幫助您。另外,作爲一名玩家,我不能遠離試圖幫助人們在那裏玩遊戲!

實時使用認證/授權層,您可以在其中爲用戶提供對頻道的讀/寫權限。當用戶進入網站時,您可以授予他們對遊戲頻道的只讀權限,並且一旦他們登錄,您就可以給他們寫入權限。這可以通過執行認證後重新連接到服務器(它可以完成客戶端)輕鬆完成。不過,我會在服務器端增加安全性。

實時有一個Node.js API,因此您可以輕鬆地將其與您的服務器集成。由於它也具有適用於許多其他平臺(包括移動平臺)的API,並且它們都以相同的方式工作,所以您可以在同一通信層實際上讓您的遊戲在多個平臺上運行,同時完全控制通道。

感謝您的閱讀。

編輯:

你可以在這裏閱讀文檔的詳細信息:http://docs.xrtml.org/