Google App Engine с интерфейсом ClientLogin для Objective-C

У меня такая же проблема с это предыдущее сообщение stackoverflow.com.

В частности, мне кажется, что я могу правильно получить токен «Auth», но попытки использовать его в заголовке, когда я обращаюсь к более поздним страницам, по-прежнему просто возвращают мне HTML-код страницы входа.

Следуя ссылкам, относящимся к этому сообщению, я определил, что вам нужно сделать следующий вызов этот URL.

После этого вызов URL-адреса даст вам файл cookie ACSID, который затем необходимо передать в последующих вызовах, чтобы поддерживать состояние аутентификации.

При запросе этого файла cookie я читал различные сообщения, в которых говорилось, что вам нужно указать исходный токен аутентификации, добавив его в строку запроса, например:

?auth=this_is_my_token

Я также читал, что вы должны установить его в заголовке http, как описано в документация Google, таким образом, чтобы имя / значение заголовка http было:

Authorization: GoogleLogin auth=yourAuthToken

Я пробовал оба подхода и не вижу возвращенных файлов cookie. Я использовал Wireshark, LiveHttpHeaders для Firefox и простые операторы 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.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
0
12 110
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Посмотрите код, который делает это в официальном SDK. В последней версии SDK он даже разделен на собственный файл.

Та же проблема. Вот чего я не понимаю, если я просто подключу: myapp.appspot.com/_ah/login?continue=http://myapp.appspot.co‌ м /… в браузере, разве я не увижу, как устанавливается cookie ???

Keith Fitzgerald 24.01.2009 00:39
Ответ принят как подходящий

Добавление примера кода к этому вопросу, потому что кто-то связался со мной напрямую по поводу моего решения. Обратите внимание, что вы должны установить параметр «service» равным «ah» в первоначальном запросе токена.

Первоначальный запрос токена [выполняется синхронно] ПРИМЕЧАНИЕ: параметр «service» установлен на «ah», а «источник» просто установлен на «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, чтобы вы получили файл cookie ASCID. Я не уверен, почему существует этот дополнительный шаг, похоже, это проблема со стороны Google и, возможно, почему GAE в настоящее время отсутствует в их перечисленной библиотеке api данных google obj-c. Мои тесты показывают, что я имеют запрашиваю cookie для синхронизации с GAE. Также обратите внимание, что я ничего не делаю с файлом 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");
    }

Это какао ... «Система загрузки URL-адресов автоматически отправляет любые сохраненные файлы cookie, подходящие для NSURLRequest, если в запросе не указано, что отправлять файлы cookie. Аналогичным образом, файлы cookie, возвращенные в NSURLResponse, принимаются в соответствии с текущей политикой принятия файлов cookie».

z8000 12.02.2009 22:12

Я не понимаю, как кто-то мог понять это из документации Google. Большое спасибо за эксперименты.

Kristopher Johnson 09.11.2009 03:48

1-й - спасибо за отличный пост, с которого я действительно начал.

2-й - я заткнул это своим приложением, пытаясь выполнить POST в GAE во время аутентификации.

Этот запрос создается при POSTing после получения токена авторизации:

    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

Обратите внимание, что Google недавно изменил способ индикации сбоя авторизации. Раньше они помещали в ответ жетон ошибки. Теперь они просто возвращают статус 403 (Запрещено). Это нарушило мой код!

Спасибо за этот пост и особенно за ответ Кита, но у меня он не работает. Даже если мне это кажется нормальным ... очень странно.

Я проверяю этот пост (Как получить доступ к службе Google App Engine с проверкой подлинности из (не веб-) клиента Python?), в котором рассказывается о том же, что и в Python. Тестирую, работает.

И объективный код C, предложенный Китом, действительно похож на код Python.

Но когда я пытаюсь получить токен «Auth», authData содержит Error = BadAuthentication.

Кто-то получил представление о возможных проблемах?

хорошо, мои проблемы просто в том, что параметр запроса (электронная почта, пароль, ....) должен быть "закодирован". Как то, что делается в python с помощью urllib.urlencode. Еще не нашел, как это сделать в objc, но все должно быть в порядке. Извините

Nicolas Hognon 20.02.2010 01:44

Использование HOSTED_OR_GOOGLE неправильно, и я объясню почему.

В мире Google есть два типа учетных записей. Те, которые вы создаете для GMail и т. д., Являются учетными записями Google. Те, которые вы создаете для приложений для доменов, являются «размещенными» учетными записями. Вы можете использовать адрес электронной почты размещенной учетной записи для создания учетной записи Google, создав таким образом адрес электронной почты, связанный с обоими типами учетных записей.

Ваше приложение Google App Engine можно настроить для работы с (1) учетными записями Google или (2) размещенными учетными записями для определенного домена.

Предположим, мы разрабатываем приложение для учетных записей Google. Пользователь вводит адрес электронной почты, связанный с учетной записью Google и размещенной учетной записью. Google будет использовать свою учетную запись Google для входа. Все работает нормально.

Теперь, если мы используем ClientLogin с тем же адресом электронной почты и используем HOSTED_OR_GOOGLE для типа учетной записи, вход будет успешным, но будет использоваться размещенная учетная запись, поскольку размещенная учетная запись имеет приоритет. Как я уже упоминал выше, вы не можете использовать размещенную учетную запись для приложения, которое ожидает учетную запись Google. Так что аутентификация работать не будет.

Таким образом, при использовании ClientLogin для аутентификации в приложении Google App Engine необходимо использовать GOOGLE для типа учетной записи, если приложение предназначено для учетных записей Google, или HOSTED для типа учетной записи, если приложение предназначено для домена.

Я создал несколько классов obj-c для реализации ClientLogin, включая поддержку Google App Engine:

http://github.com/cameronr/GoogleAppEngineAuth

Другие вопросы по теме