10

この以前のstackoverflow.comの投稿でも同じ問題が発生しています。

具体的には、「Auth」トークンを正しく取得できるようですが、後のページにアクセスするときにヘッダーで使用しようとすると、ログインページのHTMLが返されます。

この投稿に関連するリンクをたどると、このURLを後で呼び出す必要があると判断しました。

URLを呼び出すと、ACSID Cookieが提供されます。このCookieは、認証された状態を維持するために、後続の呼び出しで渡す必要があります。

このCookieをリクエストするとき、次のようにクエリ文字列に追加して元の認証トークンを指定する必要があるというさまざまな投稿を読みました。

?auth=this_is_my_token

また、 Googleのドキュメントで説明されているように、httpヘッダーの名前/値が次のようになるようにhttpヘッダーに設定する必要があることも読みました。

Authorization: GoogleLogin auth=yourAuthToken

両方のアプローチを試しましたが、Cookieが返されませんでした。私はWireshark、Firefox用のLiveHttpHeaders、およびこのようなものが返されるかどうかを確認するための単純なNSLogステートメントを使用しました。

以下は、私が使用しているコードスニペットです。

NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://yourapp.appspot.com/_ah/login?auth=%@", [token objectForKey:@"Auth"]]];
NSHTTPURLResponse* response;
NSError* error;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setValue:[NSString stringWithFormat:@"GoogleLogin auth=%@", [token objectForKey:@"Auth"]] forHTTPHeaderField:@"Authorization"];
NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];  

//show me all header fields
NSLog([[response allHeaderFields] description]);

//show me the response
NSLog(@"%@", [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease]);
NSArray * all = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:[NSURL URLWithString:@"http://yourapp.appspot.com/_ah/login"]];

//show me all cookies
for (NSHTTPCookie *cookie in all) 
{
    NSLog(@"Name: %@ : Value: %@", cookie.name, cookie.value); 
}

ClientLoginGoogleAppEngineコードに使用できることを願っています。

4

7 に答える 7

16

誰かが私のソリューションについて直接私に連絡したため、この質問にサンプルコードを追加します。最初のトークン要求で「サービス」パラメータを「ah」に設定する必要があることに注意してください。

トークンの初期リクエスト [同期的に実行] 注: 「service」パラメーターは「ah」に設定され、「source」は「myapp」に設定されているだけです。アプリ名を使用する必要があります。

//create request
NSString* content = [NSString stringWithFormat:@"accountType=HOSTED_OR_GOOGLE&Email=%@&Passwd=%@&service=ah&source=myapp", [loginView username].text, [loginView password].text];
NSURL* authUrl = [NSURL URLWithString:@"https://www.google.com/accounts/ClientLogin"];
NSMutableURLRequest* authRequest = [[NSMutableURLRequest alloc] initWithURL:authUrl];
[authRequest setHTTPMethod:@"POST"];
[authRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-type"];
[authRequest setHTTPBody:[content dataUsingEncoding:NSASCIIStringEncoding]];

NSHTTPURLResponse* authResponse;
NSError* authError;
NSData * authData = [NSURLConnection sendSynchronousRequest:authRequest returningResponse:&authResponse error:&authError];  

NSString *authResponseBody = [[NSString alloc] initWithData:authData encoding:NSASCIIStringEncoding];

//loop through response body which is key=value pairs, seperated by \n. The code below is not optimal and certainly error prone. 
NSArray *lines = [authResponseBody componentsSeparatedByString:@"\n"];
NSMutableDictionary* token = [NSMutableDictionary dictionary];
for (NSString* s in lines) {
    NSArray* kvpair = [s componentsSeparatedByString:@"="];
    if ([kvpair count]>1)
        [token setObject:[kvpair objectAtIndex:1] forKey:[kvpair objectAtIndex:0]];
}

//if google returned an error in the body [google returns Error=Bad Authentication in the body. which is weird, not sure if they use status codes]
if ([token objectForKey:@"Error"]) {
    //handle error
};

次のステップは、Google App Engine でアプリを実行して、ASCID Cookie を提供することです。なぜこの余分なステップがあるのか​​ わかりません。これはGoogle側の問題であり、おそらくGAEがリストされたobj-c GoogleデータAPIライブラリに現在含まれていない理由です。私のテストでは、GAE と同期するには Cookie を要求する必要があることがわかりました。また、私はクッキーで何もしていないことに注意してください。リクエストしてCookieを取得するだけで、今後のリクエストには自動的にCookieが含まれるようです。これが iPhone のものかどうかはわかりません。私のアプリは iPhone アプリですが、この Cookie で何が起こっているのか完全にはわかりません。注: 「myapp.appspot.com」の使用。

NSURL* cookieUrl = [NSURL URLWithString:[NSString stringWithFormat:@"http://myapp.appspot.com/_ah/login?continue=http://myapp.appspot.com/&auth=%@", [token objectForKey:@"Auth"]]];
    NSLog([cookieUrl description]);
    NSHTTPURLResponse* cookieResponse;
    NSError* cookieError;
    NSMutableURLRequest *cookieRequest = [[NSMutableURLRequest alloc] initWithURL:cookieUrl];

    [cookieRequest setHTTPMethod:@"GET"];

    NSData* cookieData = [NSURLConnection sendSynchronousRequest:cookieRequest returningResponse:&cookieResponse error:&cookieError];   

最後に、json を gae アプリに投稿できます。注: 以下のスニペットは非同期リクエストです。didReceiveResponse、didReceiveData、didFailWIthError を実装することで、応答を処理できます。

NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://myapp.appspot.com/addRun?auth=%@", mytoken]];
    NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:@"my http body";

    NSURLConnection *connectionResponse = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (!connectionResponse) {
        NSLog(@"Failed to submit request");
    } else {
        NSLog(@"Request submitted");
    }
于 2009-01-26T01:08:05.990 に答える
1

1st - 本当に私を始めさせてくれた素晴らしい投稿をありがとう。

2番目-認証中にGAEにPOSTしようとして、アプリでそれを長引かせています。

これは、authtoken を取得すると、POST 時に作成されるリクエストです。

    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];


[request setURL:[NSURL URLWithString:url]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"image/png" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];

[request setValue:authtoken forHTTPHeaderField:@"auth"];  // <-- the magic
  • マット
于 2009-02-28T02:48:01.537 に答える
1

Google App Engine のサポートを含む、ClientLogin を実装するための obj-c クラスをいくつか作成しました。

http://github.com/cameronr/GoogleAppEngineAuth

于 2010-03-08T22:58:48.483 に答える
1

公式 SDK でこれを行うコードを確認してください。最新の SDK リリースでは、独自のファイルに分割されています。

于 2009-01-23T19:22:15.323 に答える
0

HOSTED_OR_GOOGLE の使用は間違っています。その理由を説明します。

Google の世界には 2 種類のアカウントがあります。Gmail などで作成するのは「Google」アカウントです。ドメイン向けアプリ用に作成するものは、「ホストされた」アカウントです。Hosted Account のメールを使用して Google アカウントを作成すると、両方の種類のアカウントに関連付けられたメール アドレスを作成できます。

Google App Engine アプリは、(1) Google アカウントまたは (2) 特定のドメインのホストされたアカウントで動作するように構成できます。

Google アカウント用のアプリを開発しているとします。ユーザーは、Google アカウントとホストされたアカウントに関連付けられているメール アドレスを入力します。Google はログインに Google アカウントを使用します。これはすべてうまくいきます。

この同じメール アドレスで ClientLogin を使用し、アカウント タイプに HOSTED_OR_GOOGLE を使用すると、ログインは成功しますが、ホスト アカウントが優先されるため、ホスト アカウントが使用されます。上で述べたように、Google アカウントを必要とするアプリにホスト型アカウントを使用することはできません。したがって、認証は機能しません。

そのため、ClientLogin を使用して Google App Engine アプリで認証する場合、アプリが Google アカウント用の場合はアカウント タイプに GOOGLE を使用するか、アプリがドメイン用の場合はアカウント タイプに HOSTED を使用する必要があります。

于 2010-03-06T12:56:13.140 に答える
0

この投稿、特にキースからの回答に感謝しますが、私にはうまくいきません。私には大丈夫そうに見えても...とても奇妙です。

Pythonで同じことを行うことについて説明しているこの投稿 ( (非 Web) Python クライアントから認証済みの Google App Engine サービスにアクセスするにはどうすればよいですか? ) をチェックします。私はそれをテストし、それは動作します。

そして、Keith によって提案された目的の C コードは、Python コードに非常に似ています。

しかし、「Auth」トークンを取得しようとすると、authData に Error=BadAuthentication が含まれています。

考えられる問題について誰かが考えましたか?

于 2010-02-19T22:13:41.050 に答える
0

Google は最近、承認の失敗を示す方法を変更したことに注意してください。以前は、応答にエラー トークンを配置していました。現在は 403 (Forbidden) ステータスを返すだけです。これは私のコードを壊しました!

于 2009-12-03T15:11:13.453 に答える