2012-01-31 98 views
1

我试图使用Java/Groovy客户端访问Google App Engine上的受OAuth保护的资源。但是,身份验证不起作用,我的GET请求只是将Google帐户登录页面HTML带回。访问Google App Engine上的受oauth保护的资源

我使用HTTPBuilder/signpost和google-oauth-java-client获得相同的结果。

这里是我做了什么:

  • 设立一个OAuth提供者在http://ikaisays.com/2011/05/26/setting-up-an-oauth-provider-on-google-app-engine/
  • 创建映射了一个 '世界你好' 的servlet(实际上是Gaelyk的Groovlet)描述http://<my-app>.appspot.com/rest/hello
  • 部署的servlet to gae并确认我可以通过浏览器进行GET。
  • 为我的web.xml添加了安全性约束并重新部署。

    <security-constraint> 
         <web-resource-collection> 
          <web-resource-name>Rest</web-resource-name> 
          <url-pattern>/rest/*</url-pattern> 
         </web-resource-collection> 
         <auth-constraint> 
          <role-name>*</role-name> 
         </auth-constraint> 
    </security-constraint> 
    
  • 证实,一个浏览器中得到需要一个谷歌帐户登录和登录后,我可以访问servlet。

  • 做了三足式OAuth舞蹈作为http://groovy.codehaus.org/modules/http-builder/doc/auth.html描述来获得访问和客户端秘密凭证。
  • 使用令牌的RESTClient实现如下(在上面的链接下面的说明)

    def client = new RESTClient('http://<my-app>.appspot.com') 
    def consumerKey = <my consumer key> 
    def consumerSecret = <my consumer secret> 
    def accessToken = <my access token> 
    def secretToken = <my secret token> 
    client.auth.oauth consumerKey, consumerSecret, accessToken, secretToken 
    def resp = client.get(path:'/rest/hello') 
    assert resp.data == 'Hello world' 
    
  • 因为响应是谷歌帐户登录页面断言失败。

  • 当使用google-oauth-java-client时,我得到相同的行为。

我已经完成了上述几个过程,检查标记中的复制/粘贴错误,并确保我没有混入令牌。

这与Groovy 1.8.2,OSX Java 1.6.0_29,HTTPBuilder 0.5.1,gaelyk 1.1。

任何想法?谢谢。所以这里

回答

2

OK,没有这方面的反应就是我的工作围绕它。

我放弃了使用OAuth ... Google只要求“实验性”的地位这个反正所以也许它根本还没有工作。

但是我得到使用的ClientLogin协议从我的测试客户端,我根据这个就非常有用的文章http://www.geekyblogger.com/2011/05/using-clientlogin-to-do-authentication.html了良好的效果(等同于做一个手动登录到谷歌帐户就像使用Gmail时,你做的一个)

。我不得不在几个方面扩展,代码如下:

import java.io.File;   
import java.io.InputStream;   
import java.io.LineNumberReader;   
import java.io.StringReader;   
import java.nio.charset.Charset;   

import org.apache.commons.io.IOUtils;   
import org.apache.http.Header;   
import org.apache.http.HttpResponse;   
import org.apache.http.client.HttpClient;   
import org.apache.http.client.methods.HttpGet;   
import org.apache.http.client.methods.HttpPost;   
import org.apache.http.entity.mime.MultipartEntity;   
import org.apache.http.entity.mime.content.StringBody;   
import org.apache.http.impl.client.DefaultHttpClient;   

import com.google.appengine.repackaged.com.google.common.io.Files;   
import com.google.cloud.sql.jdbc.internal.Charsets;   

public class Login {   

    public static void main(String[] args) throws Exception {   
     // This file contains my   
     // google password. Note that this has to be an app-specific   
     // password if you use 2-step verification   
     File passFile = new File("/Users/me/pass.txt");   
     String pass = Files.toString(passFile, Charsets.UTF_8);   
     String authCookie = loginToGoogle("[email protected]", pass,   
       "http://myapp.appspot.com");   
     DefaultHttpClient client = new DefaultHttpClient();   
     // A te   
     HttpGet get = new HttpGet("http://myapp.appspot.com/rest/blah");   
     get.setHeader("Cookie", authCookie);   
     HttpResponse response = client.execute(get);   
     response.getEntity().writeTo(System.out);   
    }   

    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(  
       "YourCompany-YourApp-YourVersion"));   
     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");   
    }   

}