2013-03-14 78 views
5

我試圖設置一個Sign in with Google按鈕,該按鈕允許用戶在我的網站上購買物品。在客戶端登錄後對服務器端的G +用戶進行身份驗證

客戶端認證看起來非常簡單,但我很努力地理解服務器端認證是如何工作的。在example code中,它們將客戶端「代碼」參數傳遞給服務器,在該服務器中可以交換訪問令牌,然後可以使用該令牌查看用戶朋友的列表。

但我不想看到用戶的朋友列表。我只想確定客戶實際上是他們自稱的客戶。

取回令牌後,示例代碼將該令牌放入會話中,似乎使用該令牌的存在來驗證用戶是否已通過身份驗證。這是正確的/安全的嗎?應該(不)我的服務器以何種方式重新驗證令牌(如何?)何時需要購買?我是否應該每次向Google重新驗證令牌? (希望不是?)

+0

我發佈了一個相關的問題,因爲我認爲使用Facebook API執行此操作的標準方法是使用signed_request參數,但Google似乎沒有相應的參數。 http://stackoverflow.com/questions/15395142/does-google-javascript-api-have-an-equivalent-to-facebooks-signed-request – 2013-03-14 16:57:42

回答

2

在執行購買之前,您可能想要做的是通過將用戶標識從客戶端安全地傳遞到服務器並根據用戶標識進行驗證來驗證用戶是否您期望他們是誰爲存儲的憑據。這爲攻擊者通過劫持他們的會話假裝成爲您的網站用戶並在接受用戶付款之前進行的最重要的檢查提供了額外的防範重播攻擊。

我不會僅依靠用戶驗證作爲防範欺詐的機制。您應該使用安全支付系統,如Google Commerce platform,並按照the best practices for commerce

提醒一下,每次緩存的憑據初始化時,都應該使用OAuth2 v2端點來檢查您的令牌。檢查每個請求似乎有點過分,因爲您應該使用已經驗證並存儲在服務器端的緩存憑據。在更新訪問令牌時,至多可以執行檢查,但如果您信任刷新令牌,則在創建帳戶並設置刷新令牌時執行檢查時應該足夠安全。

以下步驟都採取了在除了用戶ID驗證建立帳戶時:

  • 驗證客戶端是你希望它是誰。這可以防止僞造的訪問令牌被傳遞到您的應用,以便代表攻擊者使用您的配額有效發出請求。
  • 確認該帳戶是由您的應用程序創建的,該帳戶是在代表用戶創建其他帳戶的情況下創建的。

正如您的鏈接帖子中所提到的,the Google+ quickstarts中的示例代碼應該充分說明如何使用多種編程語言對帳戶授權執行這些檢查。

中的HTML/JS客戶端,下面的代碼示出了用戶ID(值,而不是特殊的字符串「我」),以傳遞給連接方法來驗證的Google+ userID是檢索到:

var request = gapi.client.plus.people.get({'userId' : 'me'}); 
    request.execute(function(profile) { 
     $('#profile').empty(); 
     if (profile.error) { 
     $('#profile').append(profile.error); 
     return; 
     } 
     helper.connectServer(profile.id); 
     $('#profile').append(
      $('<p><img src=\"' + profile.image.url + '\"></p>')); 
     $('#profile').append(
      $('<p>Hello ' + profile.displayName + '!<br />Tagline: ' + 
      profile.tagline + '<br />About: ' + profile.aboutMe + '</p>')); 
     if (profile.cover && profile.coverPhoto) { 
     $('#profile').append(
      $('<p><img src=\"' + profile.cover.coverPhoto.url + '\"></p>')); 
     } 
    }); 

...以下代碼顯示正在傳送的Google+ ID。

connectServer: function(gplusId) { 
    console.log(this.authResult.code); 
    $.ajax({ 
    type: 'POST', 
    url: window.location.href + '/connect?state={{ STATE }}&gplus_id=' + 
     gplusId, 
    contentType: 'application/octet-stream; charset=utf-8', 
    success: function(result) { 
     console.log(result); 
     helper.people(); 
    }, 
    processData: false, 
    data: this.authResult.code 
    }); 
} 

在Java樣品中執行這些檢查相關的代碼如下:

 // Check that the token is valid. 
     Oauth2 oauth2 = new Oauth2.Builder(
      TRANSPORT, JSON_FACTORY, credential).build(); 
     Tokeninfo tokenInfo = oauth2.tokeninfo() 
      .setAccessToken(credential.getAccessToken()).execute(); 
     // If there was an error in the token info, abort. 
     if (tokenInfo.containsKey("error")) { 
     response.status(401); 
     return GSON.toJson(tokenInfo.get("error").toString()); 
     } 
     // Make sure the token we got is for the intended user. 
     if (!tokenInfo.getUserId().equals(gPlusId)) { 
     response.status(401); 
     return GSON.toJson("Token's user ID doesn't match given user ID."); 
     } 
     // Make sure the token we got is for our app. 
     if (!tokenInfo.getIssuedTo().equals(CLIENT_ID)) { 
     response.status(401); 
     return GSON.toJson("Token's client ID does not match app's."); 
     } 
     // Store the token in the session for later use. 
     request.session().attribute("token", tokenResponse.toString()); 
     return GSON.toJson("Successfully connected user."); 
    } catch (TokenResponseException e) { 
     response.status(500); 
     return GSON.toJson("Failed to upgrade the authorization code."); 
    } catch (IOException e) { 
     response.status(500); 
     return GSON.toJson("Failed to read token data from Google. " + 
      e.getMessage()); 
    } 

在該樣品中ClientID的從谷歌API控制檯來了,將是不同的應用程序。

+0

1)「傳遞用戶ID」你的意思是「代碼」參數?或用戶ID? 2)「根據存儲的憑證進行驗證」示例代碼不存儲憑證。究竟應該存儲什麼?多長時間? (數據庫?會話?)更具哲理意義的是,代碼示例似乎沒有按照您的建議做。他們呢? (比如說)Java樣本的哪些行可以完成你所說的內容? – 2013-03-16 00:32:07

+0

1)在樣本的HTML/JS客戶端(index.html)的連接方法中,您會注意到Google+ ID作爲GET參數傳遞並使用令牌信息進行驗證。 2)樣本*模擬*使用會話存儲來存儲用戶憑證的操作,並使用存儲的訪問/刷新令牌重新創建授權狀態。刷新標記不會過期,因此應該安全地保留,除非用戶斷開其帳戶。訪問令牌在3600秒後過期,因此應僅在過期時更新。第153-183行正在Java樣本中執行檢查。 – class 2013-03-17 08:15:12

+0

最後一個評論,如果你想看到一個更全面的例子,應該如何保存令牌和憑證,PhotoHunt樣本將更好地證明這一點。在這裏查看saveTokenForUser:https://github.com/googleplus/gplus-photohunt-server-java/blob/master/src/com/google/plus/samples/photohunt/ConnectServlet.java – class 2013-03-17 08:22:55

相關問題