2013-05-19 67 views
3

在OAuth2令牌交換結束時,我[通常]留下了一個用戶數據的JSON數組,我用字段I將其解組爲一個結構體(比如說GoogleUser)關心。處理OAuth響應和會話

將數據記錄到我的數據庫的明智方式是什麼?只要在回調處理程序中調用一個CreateUser函數,在檢查用戶不存在於數據庫之後,傳遞結構並保存它(顯而易見)。

我假設我應該在回調處理程序中創建會話令牌(即session.Values["authenticated"] == true),將其存儲在cookie中(具有合理的失效日期),並且只需檢查任何處理函數的if authenticated == true,這些處理函數需要登錄用戶?或者,對於管理員處理程序:if admin_user == true這裏有什麼風險(如果有)假設我正在通過HTTPS和使用安全cookie進行通話?

對基本問題表示歉意:試圖抓住「最佳實踐」方式來記錄具有OAuth功能的用戶。

回答

1

關於您的第一個問題,通常建議您在單個交易中進行檢查並插入。這取決於你使用的數據庫,但這些數據通常被稱爲UPSERT陳述。在PLSQL它看起來有點像這樣(修改味):

CREATE FUNCTION upsert_user(emailv character varying, saltv character varying, hashv character varying, date_createdv timestamp without time zone) RETURNS void 
    LANGUAGE plpgsql 
AS $$; 
BEGIN 
    LOOP 
     -- first try to update the key 
     UPDATE users SET (salt, hash) = (saltv, hashv) WHERE email = emailv; 
     IF found THEN 
      RETURN; 
     END IF; 
     -- not there, so try to insert the key 
     -- if someone else inserts the same key concurrently, 
     -- we could get a unique-key failure 
     BEGIN 
      INSERT INTO users(email, salt, hash, date_created) VALUES (emailv, saltv, hashv, date_createdv); 
      RETURN; 
     EXCEPTION WHEN unique_violation THEN 
      -- do nothing, and loop to try the UPDATE again 
     END; 
    END LOOP; 
END; 
$$; 

在問候你的第二個問題,通常Secure餅乾通過HTTPS是不夠的。我設置HttpOnly選項,通常Path選項也是如此。

HttpOnly表示cookie無法通過JS(僅HTTP或HTTPS)訪問,並且Path選項允許您指定cookie有效的路徑(在URL中)。

+0

太棒了;非常感謝。我使用RethinkDB,它不支持upserts(只是沒有SQL語法):https://github.com/rethinkdb/rethinkdb/issues/209。感謝您回答我的第二個問題:我的理解是,我真正使用Cookie運行的唯一風險是重播攻擊,但我打算有一個合理的過期(7天)來限制這一點。只要用戶不能冒充管理員或其他用戶,我就不會過分擔心。 – elithrar

+1

我認爲管理員用戶的失效時間短至30-60分鐘可能是一個好主意。他們可以做更多的傷害! 所以...我會得到獎金? :-)這很酷,如果你想等待更好的答案或更多的信息。 – Intermernet

+0

(我不得不等待12個小時才能讓它出來);) – elithrar

1

Access Token in OAuth standard has expiry。它通常由授權服務器決定。在你的情況下,我假設你在授權服務器端。

RFC 6750例如:

通常,承載令牌返回給客戶端作爲anOAuth 2.0 [RFC6749]訪問令牌響應的一部分。這種反應的一個例子是:

RFC 6749
HTTP/1.1 200 OK 
Content-Type: application/json;charset=UTF-8 
Cache-Control: no-store 
Pragma: no-cache 

{ 
    "access_token":"mF_9.B5f-4.1JqM", 
    "token_type":"Bearer", 
    "expires_in":3600, 
    "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA" 
} 

而且讀的Access Token概念:

訪問令牌提供了一個抽象層,更換不同 授權構建體(例如,用戶名和密碼)與資源服務器理解的單個 令牌。這種抽象使得 發出的訪問令牌比用於獲取它們的授權許可 更具限制性,以及去除資源服務器的需要 以理解各種各樣的認證方法。

所以在你的情況下,我不認爲需要「cookie」或「管理處理程序」。你只需要爲每個登錄的用戶生成Access Token & Refresh Token就像OAuth spec說的那樣,並且保存它的過期時間。您還可以提供與Access Token相關的散列方法,以確保它是合法請求。例如,用戶使用他們的訪問令牌生成簽名,並使用散列號& salt方法,將訪問令牌&簽名發送給服務器進行驗證。請閱讀Public Key Encryption瞭解更多詳情。

此外,您不需要將這些標記保存到數據庫中,因爲它們都是臨時資源。您還可以將所有用戶信息保存在內存中,並實現一個緩存層以將這些真正重要的信息定期保存到DB中(我現在正在使用它)以降低數據庫壓力。

+0

我的問題可能並不清楚:我正在實現一個OAuth2 *客戶端*,並試圖確定處理來自Google | GitHub |等響應的'最佳實踐'方法。一旦我用用戶的數據(名稱,電子郵件,身份證,頭像等)獲得JSON數組。我還試圖確定在用戶嘗試訪問「私人」頁面時驗證用戶的最佳方式;使用會話cookie似乎是最適合的。 – elithrar