代码之家  ›  专栏  ›  技术社区  ›  daihovey

在iPhone应用程序中使用谷歌阅读器API和OAuth

  •  2
  • daihovey  · 技术社区  · 15 年前

    我想制作一个在谷歌阅读器API上使用的应用程序。但是我发现没有官方的API来支持它——在应用商店指南/批准方面,使用非官方的API有问题吗?其他应用程序(Reeder等)会使用这个吗?

    另外,登录的最佳方法是什么?OAuth是首选方法吗?使用Janrain是个好主意吗?

    2 回复  |  直到 15 年前
        1
  •  7
  •   user156027    15 年前

    坦率地说,苹果不在乎你是否使用谷歌的非官方API。

    我在一个客户的RSS阅读器应用程序上工作,该应用程序使用谷歌阅读器进行同步。我们没有使用OAuth,而是使用标准的HTTP登录,它会返回一个cookie,在该cookie中,您必须从中提取一个令牌,以便在对各种读卡器URL的连续调用中使用。

    我可以将我的(旧)概念验证应用程序中的登录代码发布给您。 它使用asihttp和一些自定义字符串类别。其思想是发送一个登录请求,获取响应并从响应的cookie头中提取会话ID/auth代码。然后您可以使用该会话ID/AUTH代码进行连续调用。

    #pragma mark -
    #pragma mark login
    
    //this is your sessionID token you get from the login
    //use this in consecutive calls to google reader
    //this method returns you the header string you have to add to your request
    //[request addRequestHeader: @"Cookie" value: [self sidHeader]];
    - (NSString *) sidHeader
    {
        return [NSString stringWithFormat: @"SID=%@", [self sid]];
    }
    
    - (NSString *) authHeader
    {
        return [NSString stringWithFormat: @"GoogleLogin auth=%@",[self auth]];
    }
    
    
    //login to your google account and get the session ID
    - (void) login
    {
        NSString *username = @"my.googlelogin@gmail.com";
        NSString *password = @"mypassword123";
        NSString *loginUrl = @"https://www.google.com/accounts/ClientLogin?client=NNW-Mac";
        NSString *source = @"NNW-Mac"; //let's fake NetNewsWire
        NSString *continueUrl = @"http://www.google.com";
    
        ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString: loginUrl]]; // log in & get cookies
        [request addRequestHeader: @"User-Agent" value: @"NetNewsWire/3.2b25 (Mac OS X; http://www.newsgator.com/Individuals/NetNewsWire/)"];
    
        [request setPostValue: username forKey: @"Email"];
        [request setPostValue: password forKey: @"Passwd"];
        [request setPostValue: @"reader" forKey: @"service"];
        [request setPostValue: source forKey: @"source"];
        [request setPostValue: continueUrl forKey: @"continue"];
    
        [request setDelegate: self];
        [request setDidFailSelector: @selector(loginRequestFailed:)];
        [request setDidFinishSelector: @selector(loginRequestFinished:)];
    
        [request start];
    }   
    
    -(void)loginRequestFinished:(ASIHTTPRequest *)request
    {
        NSString *responseString = [request responseString];
    
        //login failed
        if ([responseString containsString: @"Error=BadAuthentication" ignoringCase: YES])
        {
            [self setLastError: [self errorWithDescription: @"Bad Username/Passsword" code: 0x001 andErrorLevel: 0x00]];
    
            if ([delegate respondsToSelector: @selector(gReaderLoginDidFail:)])
            {
                [delegate gReaderLoginDidFail: self];
            }
    
            return NO;
        }
    
        //captcha required
        if ([responseString containsString: @"CaptchaRequired" ignoringCase: YES])
        {
            [self setLastError: [self errorWithDescription: @"Captcha Required" code: 0x001 andErrorLevel: 0x00]];
    
            if ([delegate respondsToSelector: @selector(gReaderLoginDidFail:)])
            {
                [delegate gReaderLoginDidFail: self];
            }
    
            return NO;
        }
    
        //extract SID + auth
        NSArray *respArray = [responseString componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]];
    
        NSString *sidString = [respArray objectAtIndex: 0];
        sidString = [sidString stringByReplacingOccurrencesOfString: @"SID=" withString: @""];
        [self setSid: sidString];
    
    NSString *authString = [respArray objectAtIndex: 2];
    authString = [authString stringByReplacingOccurrencesOfString: @"Auth=" withString: @""];
    [self setAuth: authString];
        //mesage delegate of success
        if ([delegate respondsToSelector: @selector(gReaderLoginDidSucceed:)])
        {
            [delegate gReaderLoginDidSucceed: self];
        }
    
        return YES;
    }
    
    - (void)loginRequestFailed:(ASIHTTPRequest *)request
    {
        NSError *error = [request error];
    
        //NSLog(@"login request failed with error: %@", [error localizedDescription]);
        [self setLastError: error];
    
        if ([delegate respondsToSelector: @selector(gReaderLoginDidFail:)])
        {
            [delegate gReaderLoginDidFail: self];
        }
    
    }
    

    登录后,您可以使用sid和auth将请求伪造到读卡器的API端点。

    例子:

    - (ASIHTTPRequest *) requestForAPIEndpoint: (NSString *) apiEndpoint
    {
        ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString: apiEndpoint]];
        [request addRequestHeader: @"User-Agent" value: @"NetNewsWire/3.2b25 (Mac OS X; http://www.newsgator.com/Individuals/NetNewsWire/)"];
        [request addRequestHeader: @"Cookie" value: [self sidHeader]];
        [request addRequestHeader: @"Authorization" value: [self authHeader]];
    
        return request;
    }
    

    关于谷歌阅读器及其私有API的一篇有趣的文章是 http://timbroder.com/2007/08/google-reader-api-functions.html

    请务必阅读最新评论:)

    /编辑:我更新了代码以使用auth头(Google在今年6月引入)。我想如果你想使用OAuth的话,这里就是放置你的OAuth令牌的地方。 猜测

        2
  •  6
  •   Community Mohan Dere    8 年前

    我发现:“google data apis objective-c客户端库提供了一个iphone静态库、一个mac os x框架和源代码,使通过google data apis访问数据变得容易。” code.google.com/p/gdata-objectivec-client -太棒了! 但是,它不包括读卡器API(因为它尚未发布)。

    我可以通过更改来访问API(在OAuthsampletouch示例中)

    NSString *scope = @"http://www.google.com/m8/feeds/";
    

    在oauthsamplerootview controllertouch.m到

    NSString *scope = @"http://www.google.com/reader/api/*";
    

    urlStr = @"http://www.google.com/m8/feeds/contacts/default/thin";
    

    urlStr = @"http://www.google.com/reader/atom/user/-/label/Design";
    

    其中design是文件夹名-选中此项 http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI 这是一个很大的帮助。


    更新

    从那时起,我发现这种技术是最好的/最轻的/不那么复杂的: Native Google Reader iPhone Application