Dan*_*ich 5 oauth google-plus google-oauth
我正在尝试设置一个Google登录按钮,允许用户在我的网站上购买商品.
客户端身份验证看起来非常简单,但我很难理解服务器端身份验证的工作原理.在示例代码中,它们将客户端"代码"参数传递给服务器,在该服务器中可以交换访问令牌,然后可以使用该访问令牌来查看用户朋友的列表.
但我不想看到用户朋友的列表.我只是想确定客户实际上是他们声称的那个人.
检索令牌后,示例代码将令牌放入会话中,并且似乎使用令牌的存在来验证用户是否经过身份验证.这是正确/安全吗?应该(不)我的服务器以某种方式重新验证令牌(如何?)何时进行购买?我是否应该在每次请求时不断向Google重新验证令牌?(希望不是?)
在执行购买之前,您可能想要做的是通过将用户 ID 从客户端安全地传递到服务器并根据存储的凭据的用户 ID 进行验证来验证用户是否是您期望的用户。这提供了针对重放攻击的额外保护,攻击者通过劫持会话来冒充您网站的用户,并且是在接受用户付款之前进行的最相关的检查。
我不会仅仅依赖用户验证作为防止欺诈的机制。您应该使用安全的支付系统(例如Google Commerce 平台)并遵循商业最佳实践。
提醒一下,每次初始化缓存的凭据时,应使用 OAuth2 v2 端点来检查您的令牌。检查每个请求似乎有点过多,因为您应该使用已经在服务器端验证并存储的缓存凭据。您最多可以在更新访问令牌时执行检查,但如果您信任刷新令牌,则在创建帐户并设置刷新令牌时执行检查应该足够安全。
除了创建帐户时进行用户 ID 验证之外,还执行以下步骤:
正如您的链接文章中提到的, Google+ 快速入门中的示例代码应该充分演示如何以各种编程语言执行这些检查以进行帐户授权。
在 HTML/JS 客户端中,以下代码显示了检索 userId(值,而不是特殊字符串“me”)的位置,以传递给 connect 方法以验证 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>'));
}
});
Run Code Online (Sandbox Code Playgroud)
...以下代码显示了正在传递的 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
});
}
Run Code Online (Sandbox Code Playgroud)
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());
}
Run Code Online (Sandbox Code Playgroud)
在示例中,ClientID 来自 Google API 控制台,并且对于您的应用程序来说是不同的。
| 归档时间: |
|
| 查看次数: |
2947 次 |
| 最近记录: |