Google App Engine z interfejsem ClientLogin dla Objective-C

Mam ten sam problem w tym poprzednim stackoverflow.com post .

W szczególności wydaje mi się, że jestem w stanie poprawnie uzyskać token "Auth", ale próby użycia go w nagłówku, gdy uzyskuję dostęp do późniejszych stron, nadal zwracają mi HTML strony logowania.

Po linkach związanych z tym postem ustaliłem, że musisz wykonać kolejne połączenie na ten URL .

Wywołanie adresu URL spowoduje wyświetlenie pliku cookie ACSID, który następnie musi być przekazywane w kolejnych wywołaniach w celu utrzymania uwierzytelnionego stanu.

Kiedy prosiłem o ten plik cookie, czytałem różne posty mówiące, że musisz podać swój oryginalny token auth, dodając go do ciągu zapytania, tak aby:

?auth=this_is_my_token

Czytałem również, że należy ustawić go w nagłówku http, jak opisano w dokumentacja google tak, aby nazwa/wartość nagłówka http brzmiała:

Authorization: GoogleLogin auth=yourAuthToken

Próbowałem obu podejść i nie widzę żadnych ciasteczek zwróconych. Używałem Wireshark, LiveHttpHeaders for Firefox i proste instrukcje NSLog próbujące sprawdzić, czy coś takiego zostanie zwrócone.

Poniżej znajduje się fragment kodu, którego używałem.

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); 
}

Mam nadzieję, że możesz użyć ClientLogin dla kodu Google App Engine.

Author: Community, 2009-01-23

7 answers

Dodanie przykładowego kodu do tego pytania, ponieważ ktoś skontaktował się ze mną bezpośrednio w sprawie mojego rozwiązania. Zauważ, że musisz ustawić parametr "service "równy" ah " w początkowym żądaniu tokena.

Początkowe żądanie Tokena [wykonane synchronicznie] Uwaga: parametr " service "jest ustawiony na "ah", a "source" jest po prostu ustawiony na "myapp", powinieneś użyć nazwy aplikacji.

//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
};

Następnym krokiem jest uruchomienie aplikacji na Google app engine, aby dać Ci plik cookie ASCID. Nie wiem dlaczego tam jest to dodatkowy krok, wydaje się być problemem na końcu google i prawdopodobnie dlatego GAE nie jest obecnie w ich liście obj-C Google data api library. Moje testy pokazują, że mam , aby zażądać pliku cookie w celu synchronizacji z GAE. Zauważ też, że nic nie robię z ciasteczkiem. Wygląda na to, że po prostu żądając go i gotując, przyszłe żądania automatycznie będą zawierały plik cookie. Nie jestem pewien, czy jest to rzecz iphone BC moja aplikacja jest aplikacja iphone ale nie do końca rozumiem, co się dzieje z to ciasteczko. Uwaga: użycie "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];   
W końcu mogę dodać json do mojej aplikacji gae. Uwaga: poniższy fragment jest żądaniem asynchronicznym. Odpowiedzi możemy obsłużyć implementując 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");
    }
 16
Author: Keith Fitzgerald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 01:08:05

Sprawdź kod, który to robi w oficjalnym SDK. Najnowsza wersja SDK ma nawet podzielony na własny plik .

 1
Author: Nick Johnson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-23 19:22:15

Pierwszy - dzięki za świetny post, który naprawdę dał mi początek.

2nd - byłem slugging go z mojej aplikacji, starając się wysłać do GAE podczas uwierzytelniania.

To jest żądanie jest budowane podczas wysyłania, po nabyciu 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
 1
Author: Matt B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-28 02:48:01

Stworzyłem kilka klas obj-c do implementacji ClientLogin, w tym wsparcie dla Google App Engine:

Http://github.com/cameronr/GoogleAppEngineAuth

 1
Author: Cam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-08 22:58:48

Zauważ, że Google ostatnio zmieniło sposób Wskazywania awarii autoryzacji. W odpowiedzi umieszczano token błędu. Teraz po prostu zwracają status 403 (zakazany). To złamało mój kod!

 0
Author: phatmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-03 15:11:13

Dziękuję za ten post, a zwłaszcza odpowiedź od Keitha, ale to nie działa dla mnie. Nawet jeśli wydaje mi się to w porządku ... bardzo dziwne.

Sprawdzam ten post ( Jak uzyskać dostęp do uwierzytelnionej usługi Google App Engine z (nie-web) klienta Pythona?), które mówią o robieniu tego samego w Pythonie. Testuję i działa.

A kod objective C zaproponowany przez Keitha jest bardzo podobny do kodu Pythona.

Ale kiedy próbuję uzyskać" Auth " token authData zawiera błąd = BadAuthentication.

Ktoś ma pojęcie o możliwych problemach ?

 0
Author: Nicolas Hognon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:13:31

Używanie HOSTED_OR_GOOGLE jest złe i wyjaśnię dlaczego.

Istnieją dwa rodzaje kont w świecie Google. Te, które tworzysz dla Gmaila itp., To konta "Google". Te, które tworzysz dla aplikacji dla domen, to konta "hostowane". Możesz użyć adresu e-mail konta hostowanego, aby utworzyć konto Google, tworząc w ten sposób adres e-mail powiązany z obu rodzajami kont.

Twoja aplikacja Google App Engine może być skonfigurowana do pracy z (1) kontami Google lub (2) hostowanymi Konta dla konkretnej domeny.

Załóżmy, że tworzymy aplikację dla kont Google. Użytkownik wprowadza adres e-mail powiązany z kontem Google i kontem hostowanym. Google użyje swojego konta Google do logowania. To wszystko działa dobrze.

Teraz, jeśli użyjemy ClientLogin z tym samym adresem e-mail i użyjemy HOSTED_OR_GOOGLE dla typu konta, logowanie się zakończy się sukcesem, ale użyje konta hostowanego, ponieważ konto hostowane ma pierwszeństwo. As I wspomniano powyżej, nie można używać konta hostowanego dla aplikacji, która oczekuje konta Google. Więc uwierzytelnianie nie będzie działać.

Tak więc, gdy używasz ClientLogin do uwierzytelniania za pomocą aplikacji Google App Engine, musisz użyć GOOGLE dla typu konta, Jeśli aplikacja jest dla kont Google, lub HOSTED dla typu konta, Jeśli aplikacja jest dla domeny.

 0
Author: user287725,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-06 12:56:13