将Google登录按钮与Java应用程序集成时获取异常

时间:2014-02-19 09:31:23

标签: java spring google-api google-login google-authenticator

我正在尝试将Google登录按钮与我的Java应用程序集成。我这样做......

控制器端 -

   @RequestMapping(value = "/lnregister", method = RequestMethod.GET)
   public String doLnRegister(@RequestHeader(value = "referer", required = false) final String referer, final RegisterForm form,
        final BindingResult bindingResult, final Model model, final HttpServletRequest request,
        final HttpServletResponse response, final RedirectAttributes redirectModel) throws CMSItemNotFoundException, IOException
{
    response.setContentType("text/html");
    final String state = new BigInteger(130, new SecureRandom()).toString(32);
    request.getSession().setAttribute("state", state);

    response.setContentType("application/json");

    final String tokenData = (String) request.getSession().getAttribute("token");
    if (tokenData != null)
    {
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().print(GSON.toJson("Current user is already connected."));
        return tokenData;
    }

    final ByteArrayOutputStream resultStream = new ByteArrayOutputStream();
    getContent(request.getInputStream(), resultStream);

    final String code = new String(resultStream.toByteArray(), "UTF-8");

    try
    {
        // Upgrade the authorization code into an access and refresh token.
        final GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(TRANSPORT, JSON_FACTORY, CLIENT_ID,
                CLIENT_SECRET, code, "postmessage").execute();

        // You can read the Google user ID in the ID token.
        // This sample does not use the user ID.
        final GoogleIdToken idToken = tokenResponse.parseIdToken();
        final String gplusId = idToken.getPayload().getSubject();
        System.out.print("gplusId >>>>>>>>>>>>>>>>>>>>>>" + gplusId);
        // Store the token in the session for later use.
        request.getSession().setAttribute("token", tokenResponse.toString());
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().print(GSON.toJson("Successfully connected user."));
    }
    catch (final TokenResponseException e)
    {
        System.out.println("TokenResponseException :" + e);
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        response.getWriter().print(GSON.toJson("Failed to upgrade the authorization code."));
    }
    catch (final IOException e)
    {
        System.out.println("IOException :" + e);
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        response.getWriter().print(GSON.toJson("Failed to read token data from Google. " + e.getMessage()));
    }


}


static void getContent(final InputStream inputStream, final ByteArrayOutputStream outputStream) throws IOException
{
    // Read the response into a buffered stream
    final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    int readChar;
    while ((readChar = reader.read()) != -1)
    {
        outputStream.write(readChar);
    }
    reader.close();
}

正面JS -

<script type="text/javascript">
(function() {
  var po = document.createElement('script');
  po.type = 'text/javascript'; po.async = true;
  po.src = 'https://plus.google.com/js/client:plusone.js';
  var s = document.getElementsByTagName('script')[0];
  s.parentNode.insertBefore(po, s);
})();
</script>
 <!-- JavaScript specific to this application that is not related to API
 calls -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js" ></script>
<div id="gConnect">
  <button class="g-signin"
    data-scope="https://www.googleapis.com/auth/plus.login"
    data-requestvisibleactions="http://schemas.google.com/AddActivity"
    data-clientId="*****************"
    data-accesstype="offline"
    data-callback="onSignInCallback"
    data-theme="dark"
    data-cookiepolicy="single_host_origin">
</button>
</div>
<div id="authOps" style="display:none">
<h2>User is now signed in to the app using Google+</h2>
<p>If the user chooses to disconnect, the app must delete all stored
information retrieved from Google for the given user.</p>
<button id="disconnect" >Disconnect your Google account from this app</button>

<h2>User's profile information</h2>
<p>This data is retrieved client-side by using the Google JavaScript API
client library.</p>
<div id="profile"></div>

<h2>User's friends that are visible to this app</h2>
<p>This data is retrieved from your server, where your server makes
an authorized HTTP request on the user's behalf.</p>
<p>If your app uses server-side rendering, this is the section you
would change using your server-side templating system.</p>
<div id="visiblePeople"></div>

<h2>Authentication Logs</h2>
<pre id="authResult"></pre>
</div>

<script type="text/javascript">
var helper = (function() {
var authResult = undefined;

return {
/**
 * Hides the sign-in button and connects the server-side app after
 * the user successfully signs in.
 *
 * @param {Object} authResult An Object which contains the access token and
 *   other authentication information.
 */
onSignInCallback: function(authResult) {
  $('#authResult').html('Auth Result:<br/>');
  for (var field in authResult) {
    $('#authResult').append(' ' + field + ': ' + authResult[field] + '<br/>');
  }
  if (authResult['access_token']) {
    // The user is signed in
    this.authResult = authResult;
    helper.connectServer();
    // After we load the Google+ API, render the profile data from Google+.
    gapi.client.load('plus','v1',this.renderProfile);
  } else if (authResult['error']) {
    // There was an error, which means the user is not signed in.
    // As an example, you can troubleshoot by writing to the console:
    console.log('There was an error: ' + authResult['error']);
    $('#authResult').append('Logged out');
    $('#authOps').hide('slow');
    $('#gConnect').show();
  }
  console.log('authResult', authResult);
},
/**
 * Retrieves and renders the authenticated user's Google+ profile.
 */
renderProfile: function() {
  var request = gapi.client.plus.people.get( {'userId' : 'me'} );
  request.execute( function(profile) {
      $('#profile').empty();
      if (profile.error) {
        $('#profile').append(profile.error);
        return;
      }

      $('#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>'));
      }
    });
  $('#authOps').show('slow');
  $('#gConnect').hide();
},
/**
 * Calls the server endpoint to disconnect the app for the user.
 */
disconnectServer: function() {
  // Revoke the server tokens
  $.ajax({
    type: 'POST',
    url: window.location.href + 'disconnect',
    async: false,
    success: function(result) {
      console.log('revoke response: ' + result);
      $('#authOps').hide();
      $('#profile').empty();
      $('#visiblePeople').empty();
      $('#authResult').empty();
      $('#gConnect').show();
    },
    error: function(e) {
      console.log(e);
    }
   });
   },
/**
 * Calls the server endpoint to connect the app for the user. The client
 * sends the one-time authorization code to the server and the server
 * exchanges the code for its own tokens to use for offline API access.
 * For more information, see:
 *   https://developers.google.com/+/web/signin/server-side-flow
 */
 connectServer: function() {
  console.log(this.authResult.code);
  $.ajax({
    type: 'GET',
    url: "/store/en/login/lnregister",
    contentType: 'application/octet-stream; charset=utf-8',
    success: function(result) {
      console.log(result);
      helper.people();
    },
    processData: false,
    data: this.authResult.code
  });
  },
/**
 * Calls the server endpoint to get the list of people visible to this app.
 */
 people: function() {
  $.ajax({
    type: 'GET',
    url: window.location.href + 'people',
    contentType: 'application/octet-stream; charset=utf-8',
    success: function(result) {
      helper.appendCircled(result);
    },
    processData: false
  });
 },
/**
 * Displays visible People retrieved from server.
 *
 * @param {Object} people A list of Google+ Person resources.
 */
appendCircled: function(people) {
  $('#visiblePeople').empty();

  $('#visiblePeople').append('Number of people visible to this app: ' +
      people.totalItems + '<br/>');
  for (var personIndex in people.items) {
    person = people.items[personIndex];
    $('#visiblePeople').append('<img src="' + person.image.url + '">');
  }
 },
 };
 })();

 /**
 * Perform jQuery initialization and check to ensure that you updated your
 * client ID.
 */
 $(document).ready(function() {
   $('#disconnect').click(helper.disconnectServer);
      if ($('[data-clientid="YOUR_CLIENT_ID"]').length > 0) {
        alert('This sample requires your OAuth credentials (client ID) ' +
        'from the Google APIs console:\n' +
        'https://code.google.com/apis/console/#:access\n\n' +
        'Find and replace YOUR_CLIENT_ID with your client ID and ' +
        'YOUR_CLIENT_SECRET with your client secret in the project sources.'
   );
  }
 });

这里当我点击SignIn按钮,请求转到控制器但我得到了TokenResponseException

TokenResponseException :com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
  "error" : "invalid_request"
}

我正在使用profile来获取姓名,图片等,但我无法在那里获得email_address。 我尝试获取profile.emailprofile.emailAddress这样的电子邮件地址,但收到了undefined

我试图用很多方式整合谷歌登录,但没有得到任何运气。请帮忙。

我的相关帖子是there

1 个答案:

答案 0 :(得分:0)

您需要向数据范围添加电子邮件

<button class="g-signin"
    data-scope="https://www.googleapis.com/auth/plus.login email"