2009-01-23 123 views
10

我在this previous stackoverflow.com post中遇到了同樣的問題。具有Objective-C客戶端登錄界面的Google App Engine

具體來說,我似乎能夠正確地獲得「Auth」標記,但是當我訪問後面的頁面時,試圖在標題中使用它仍然只是返回登錄頁面的HTML。

以下與這篇文章相關的鏈接,我已確定您需要進行後續調用this URL

對URL的調用會給你一個ACSID cookie,然後需要在隨後的調用中傳遞該cookie以保持已認證的狀態。

當請求此cookie,我讀過各個崗位說你需要通過將其追加到查詢字符串指定你原來的身份驗證令牌這樣的:

?auth=this_is_my_token 

我也看到了,你應該設置它在google's documentation使得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); 
} 

我希望您可以使用ClientLogin作爲Google App Engine代碼。

回答

16

向此問題添加示例代碼,因爲有人直接與我聯繫瞭解我的解決方案。請注意,您必須在初始令牌請求中將「service」參數設置爲「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 
}; 

下一步是讓您的應用在谷歌應用引擎上運行,爲您提供ASCID cookie。我不知道爲什麼有這個額外的步驟,它似乎是谷歌的一個問題,可能爲什麼GAE目前不在他們列出的obj-c谷歌數據API庫。我的測試顯示我要求cookie與GAE同步。另外,請注意我不會對cookie做任何事情。這似乎只是通過請求它並煮熟,未來的請求將自動包含cookie。我不知道這是否是iphone的事情BC我的應用程序是一個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"); 
    } 
+0

這是一個Cocoa的東西......「URL加載系統會自動發送任何適合NSURLRequest的存儲cookie,除非請求指定不發送cookie。同樣,根據當前的cookie接受策略,接受在NSURLResponse中返回的cookie。 – z8000 2009-02-12 19:12:49

1

查看在官方SDK中執行此操作的代碼。最新的SDK發行版甚至已將其拆分爲its own file

+0

謝謝你了。現在測試。 – 2009-01-23 19:57:03

+0

同樣的問題。這裏是我不明白,如果我只是插入:http://myapp.appspot.com/_ah/login?continue=http://myapp.appspot.com/&auth=my_auth_token_i_just_got 進入瀏覽器,應該'我看到cookie被設置? – 2009-01-23 21:39:51

1

第一 - 感謝偉大的職位,它真的讓我開始。

第二次 - 我一直在用我的應用程序猛擊它,嘗試在通過身份驗證時發佈到GAE。

這是張貼時的要求而建,一旦你學會了的authToken:

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 
  • mattb
0

注意,谷歌最近改變了授權失敗指示。他們用來在響應中放置一個Error標記。現在他們只返回403(禁止)狀態。這打破了我的代碼!

0

感謝這篇文章,特別是基思的答案,但它不適用於我。 即使它對我來說好像...很奇怪。

我檢查這篇文章(How do you access an authenticated Google App Engine service from a (non-web) python client?),它討論了在python中做同樣的事情。我測試它,它工作。

Keith提出的目標C代碼與python代碼非常相似。

但是,當我嘗試獲得「Auth」令牌authData包含Error = BadAuthentication。

有人對可能出現的問題有所瞭解嗎?

0

使用HOSTED_OR_GOOGLE是錯誤的,我將解釋原因。

Google世界中有兩種帳戶。您爲GMail創建的那些是「Google」帳戶。您爲Apps for Domains創建的是「託管」帳戶。您可以使用託管帳戶電子郵件創建Google帳戶,從而創建與這兩種帳戶關聯的電子郵件地址。

您的Google App Engine應用可以配置爲與(1)Google帳戶或(2)特定域的託管帳戶一起使用。

假設我們正在開發Google帳戶的應用程序。用戶輸入與Google帳戶和託管帳戶相關聯的電子郵件地址。 Google將使用他們的Google帳戶進行登錄。這一切工作正常。

現在,如果我們對ClientLogin使用相同的電子郵件地址並使用HOSTED_OR_GOOGLE作爲帳戶類型,登錄將會成功,但它將使用託管帳戶,因爲託管帳戶優先。正如我上面提到的,您不能爲需要Google帳戶的應用使用託管帳戶。所以身份驗證將不起作用。

因此,當使用ClientLogin使用Google App Engine應用程序進行身份驗證時,如果應用程序用於Google帳戶,則需要使用GOOGLE帳戶;如果應用程序用於域,則需要使用GOOGLE帳戶類型HOSTED。

相關問題