客户端登录后,在服务器端验证 G+ 用户 [英] Authenticating G+ users on the server side, after client-side login

查看:20
本文介绍了客户端登录后,在服务器端验证 G+ 用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试设置一个 使用 Google 登录按钮将允许人们在我的网站上购买东西.

I'm trying to set up a Sign in with Google button that will allow people to purchase things on my website.

客户端身份验证看起来很简单,但我很难理解服务器端身份验证的工作原理.在 示例中code 他们将客户端的code"参数传递给服务器,在那里可以用它来换取访问令牌,然后可以用它来查看用户的朋友列表.

Client-side authentication looks pretty straightforward, but I'm struggling to understand how the server-side authentication works. In the example code they pass the client-side "code" parameter to the server, where it can be traded in for an access token, which can then be used to see the list of the user's friends.

但是我不想看到用户的好友列表.我只是想确定客户确实是他们声称的人.

But I don't want to see the list of the user's friends. I just want to be certain that the client is actually who they claim to be.

在检索到令牌后,示例代码将令牌放入会话中,并且似乎使用令牌的存在来验证用户是否已通过身份验证.那是正确的/安全的吗?应该(不)我的服务器在购买时以某种方式(如何?)重新验证令牌?我是否应该针对每个请求不断地与 Google 重新验证令牌?(希望不是?)

After retrieving the token, the sample code puts the token in the session, and seems to use the presence of the token to verify that the user is authenticated. Is that correct/safe? Should(n't) my server re-verify the token somehow (how?) when it's time to do a purchase? Should I constantly re-verify the token with Google on every request? (Hopefully not?)

推荐答案

在执行购买之前,您可能想要做的是通过将用户 ID 从客户端安全地传递到您的服务器并根据存储凭据的用户 ID 对其进行验证.这提供了针对重放攻击的额外保护,攻击者通过劫持他们的会话来伪装成您站点的用户,并且是在接受用户付款之前进行的最相关检查.

What you might want to do before performing a purchase is to verify the user is who you expect them to be by securely passing the user id from the client to your server and verifying it against the user id for the stored credentials. This offers additional protection against replay attacks where an attacker is pretending to be your site's user by hijacking their session and is the most relevant check to make before accepting payment from the user.

我不会仅仅依靠用户验证作为防止欺诈的机制.您应该使用安全的支付系统,例如 Google Commerce 平台 并遵循 商业最佳实践.

I would not rely on user validation alone as a mechanism for protection against fraud. You should use a secure payment system such as the Google Commerce platform and follow the best practices for commerce.

提醒一下,每次初始化缓存的凭据时,都应使用 OAuth2 v2 端点来检查您的令牌.检查每个请求似乎有点过分,因为您应该使用已经过验证并存储在服务器端的缓存凭据.您最多可以在更新访问令牌时执行检查,但如果您信任刷新令牌,则在创建帐户并设置刷新令牌时执行检查应该足够安全.

As a reminder, the OAuth2 v2 endpoint should be used to check your token every time the cached credentials are initialized. Checking on every request seems a bit excessive because you should be using cached credentials that have already been validated and stored server-side. At most, you could perform the checks when you update an access token but if you trust your refresh token, you should be sufficiently safe if you perform the checks when you create the account and set that refresh token.

除了在创建帐户时验证用户 ID 之外,还采取以下步骤:

The following steps are taken in addition to the user id validation upon account creation:

正如您在链接的帖子中提到的,Google+ 快速入门 中的示例代码应该足以说明如何执行这些检查使用多种编程语言进行帐户授权.

As mentioned in your linked post, the sample code in the Google+ quickstarts should sufficiently demonstrate how to perform these checks in a variety of programming languages for account authorization.

在 HTML/JS 客户端中,以下代码显示了在哪里检索 userId(值,而不是特殊字符串me")以传递给 connect 方法以验证 Google+ userId:

Within the HTML/JS client, the following code shows where the userId (value, as opposed to the special string "me") is retrieved for passing to the connect method to verify the 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.

... and the following code shows the Google+ id being passed.

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 示例中执行这些检查的相关代码如下:

The relevant code performing these checks in the Java sample is as follows:

      // 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 来自 Google API 控制台,并且对于您的应用程序来说是不同的.

In the samples, the ClientID came from the Google API console and will be distinct for your application.

这篇关于客户端登录后,在服务器端验证 G+ 用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆