iphone - 在 iPhone 应用程序中使用 Google Reader API 和 OAuth

标签 iphone objective-c oauth google-reader

我想制作一个在 Google Reader API 上使用的应用。但我发现它没有官方 API - 使用非官方 API 是否存在应用商店指南/批准方面的问题?其他应用程序(Reeder 等)会使用它吗?

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

最佳答案

坦率地说,Apple 并不关心您是否使用 Google 的非官方 API。

我为一位客户开发了 RSS 阅读器应用,该应用使用 Google 阅读器进行同步。我们没有使用 OAuth,而是使用标准 HTTP 登录,它会返回一个 cookie,您必须从中提取一个 token ,以便在对各种阅读器 URL 的连续调用中使用。

我可以向您发布我的(旧)概念验证应用程序中的登录代码。 它使用 ASIHTTP 和一些自定义字符串类别。这个想法是发送登录请求、获取响应并从响应的 cookie header 中提取 session ID/授权代码。然后您可以使用该 session ID/授权代码进行连续调用。

#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 伪造对 Reader 的 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;
}

关于 Google Reader 及其私有(private) API 的有趣读物是 http://timbroder.com/2007/08/google-reader-api-functions.html

请务必阅读最新评论:)

/edit:我更新了代码以使用 auth header (谷歌于今年 6 月引入)。我想如果您要使用 OAuth,这将是放置您的 OAuth token 的地方。

关于iphone - 在 iPhone 应用程序中使用 Google Reader API 和 OAuth,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3766643/

相关文章:

ios - 在 UIBarButtonItem 上添加手势

iphone - 从海外调用美国电话的最佳方式?

ios - google chromecast iOS SDK 是否支持锁屏控件?

ios - 展开有关在自动布局中更改方向和屏幕尺寸的 View

iphone - Objective C/iOS 中 Ruby method_missing 的等价物

ios - 如何跟踪转推和 Facebook 评论?

ios - CollectionView 不包含 CollectionViewCell

iphone - UIViewController 不调用 dealloc 或调用它两次

oauth - 帐户链接成功但访问 token 显示无效 - Google OAuth

linux - 如何允许应用程序声明 "https"方案 URI? (即如何从 https URL 打开桌面应用程序?)