使用带有服务帐户的GoogleCredential对Google App Engine服务进行身份验证

问题描述 投票:0回答:0

我有一个GAE应用程序,该应用程序具有需要身份验证的端点,我从应用程序(而不是在浏览器中)调用该身份验证。

这是来自web.xml的端点的GAE规范

<!-- Secure sensitive URLs -->
<security-constraint>
    <web-resource-collection>
        <url-pattern>/gcm/home</url-pattern>
        <url-pattern>/gcm/send</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>  

以前,在客户端应用程序中,我在调用端点之前使用ClientLogin向Google进行身份验证。 这是我使用的代码,提取了“ Auth”令牌,然后将其用作HTTP GET上上述端点的Cookie。

public static String loginToGoogle(String userid, String password,        
        String appUrl) throws Exception {        
    HttpClient client = new DefaultHttpClient();        
    HttpPost post = new HttpPost(        
            "https://www.google.com/accounts/ClientLogin");        

    MultipartEntity reqEntity = new MultipartEntity();        
    reqEntity.addPart("accountType", new StringBody("HOSTED_OR_GOOGLE",        
            "text/plain", Charset.forName("UTF-8")));        
    reqEntity.addPart("Email", new StringBody(userid));        
    reqEntity.addPart("Passwd", new StringBody(password));        
    reqEntity.addPart("service", new StringBody("ah"));        
    reqEntity.addPart("source", new StringBody("WWWWmyappname"));        
    post.setEntity(reqEntity);        
    HttpResponse response = client.execute(post);        
    if (response.getStatusLine().getStatusCode() == 200) {        
        InputStream input = response.getEntity().getContent();        
        String result = IOUtils.toString(input);        
        String authToken = getAuthToken(result);        
        post = new HttpPost(appUrl + "/_ah/login?auth=" + authToken);        
        response = client.execute(post);        
        Header[] cookies = response.getHeaders("SET-COOKIE");        
        for (Header cookie : cookies) {        
            if (cookie.getValue().startsWith("ACSID=")) {        
                return cookie.getValue();        
            }        
        }        
        throw new Exception("ACSID cookie cannot be found");        
    } else        
        throw new Exception("Error obtaining ACSID");        
}        

private static String getAuthToken(String responseText) throws Exception {        
    LineNumberReader reader = new LineNumberReader(new StringReader(        
            responseText));        
    String line = reader.readLine();        
    while (line != null) {        
        line = line.trim();        
        if (line.startsWith("Auth=")) {        
            return line.substring(5);        
        }        
        line = reader.readLine();        
    }        
    throw new Exception("Could not find Auth token");        
}  

由于不推荐使用ClientLogin,然后再将其删除,因此我认为我有义务切换到OAuth2。 阅读文档使我相信我为此需要一个服务帐户,该帐户已在Google控制台中为GAE妥善设置。 尽管GoogleCredential构建器成功返回了授权令牌,但是如果我随后在对端点的HTTP get调用中使用该令牌,则响应始终是Google登录页面。

为什么,如果我使用令牌,GAE为何不认为我已登录并获得授权? 我是做错了还是错过了一步?

以下是尝试向Google进行身份验证,然后调用GAE端点的代码:

    String emailAddress = "[email protected]";
    JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    String emailScope = "https://www.googleapis.com/auth/userinfo.email";
    String keyFileName = "YYYYY.p12";
    String baseURL = "http://ZZZZZ.appspot.com";
    HttpTransport httpTransport;
    try {
        httpTransport = GoogleNetHttpTransport.newTrustedTransport();

        File keyFile = new File(keyFileName);
        if(!keyFile.exists()) {
            System.err.println("Key file "+keyFileName+" missing");
            System.exit(0);
        }

        GoogleCredential credential = new GoogleCredential.Builder()
        .setTransport(httpTransport)
        .setJsonFactory(JSON_FACTORY)
        .setServiceAccountId(emailAddress)
        .setServiceAccountScopes(Collections.singleton(emailScope))
        .setServiceAccountPrivateKeyFromP12File(keyFile)
        .build();

        boolean success = credential.refreshToken();
        System.out.println("Access token refresh "+ success);

        String token = credential.getAccessToken();

        System.out.println("Token "+token);

        String uri = "http://ZZZZZ.appspot.com/gcm/home";

        System.out.println("uri: " + uri);

        HttpGet get = new HttpGet(uri);
        get.setHeader("Cookie", token);

        HttpClient client = new DefaultHttpClient();
        HttpResponse response = client.execute(get);
        response.getEntity().writeTo(System.out);

典型输出:

   Access token refresh true
   Token ya29.xQGG1kxxxxxxxxxxxxxxxxxxx
   uri: http://ZZZZZ.appspot.com/gcm/home

   <!DOCTYPE html>
   <html lang="en">
      <head>
      <meta charset="utf-8">
      <meta content="width=300, initial-scale=1" name="viewport">
      <meta name="google-site-verification" content="LrdTUW9psUAMbh4Ia074-BPEVmcpBxF6Gwf0MSgQXZs">
      <title>Sign in - Google Accounts</title>
      .....

谢谢!

google-app-engine authentication google-oauth2 google-client-login
© www.soinside.com 2019 - 2024. All rights reserved.