Как автоматично да опреснявам изтекъл токен с AFOAuth2Manager?

Пиша малък iOS клиент за сървър, защитен с OAuth2.

Чудя се дали е възможно с помощта на AFOAuth2Manager[тук] автоматично опресняване на изтеклия токен.

Идеята е, че логиката за опресняване на клиента, когато сървърът отговори с 401, или генериране на грешка, когато методът за опресняване върне 401, трябва да бъде доста често срещана, така че вероятно е интегрирана в някоя библиотека.


person IgnazioC    schedule 09.03.2015    source източник
comment
Намерихте ли някакви решения?   -  person iPeo    schedule 30.03.2015
comment
не толкова далече. Приложих собствената си логика   -  person IgnazioC    schedule 31.03.2015
comment
можете ли да публикувате вашата проба или да обясните какво сте направили? търся същото.   -  person cableload    schedule 21.05.2015


Отговори (4)


Създадох подклас на AFOAuth2Manager

В този подклас отменям този метод:

- (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request
                                                    success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                                                    failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure {
    return [self HTTPRequestOperationWithRequest:request
                                         success:success
                                         failure:failure
                           checkIfTokenIsExpired:YES];
}

извикване на персонализиран метод с допълнителен параметър: checkIfTokenIsExpired. Това е необходимо, за да се избегнат безкрайни цикли.

Реализацията на този метод е ясна: ако не трябва да проверяваме токена, просто извикайте суперкласа.

if (!checkIfTokenIsExpired) {
        return [super HTTPRequestOperationWithRequest:request
                                              success:success
                                              failure:failure];
    }

в противен случай изпълняваме заявката с персонализиран блок за отказ

else {
        return [super HTTPRequestOperationWithRequest:request
                                              success:success
                                              failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
            if (operation.response.statusCode == ERROR_CODE_UNAUTHORIZED) { //1
                [self reauthorizeWithSuccess: ^{ //2
                    NSURLRequest *req = [self.requestSerializer requestByAddingHeadersToRequest:request]; //3
                    AFHTTPRequestOperation *moperation = [self HTTPRequestOperationWithRequest:req //4
                                                                                       success:success
                                                                                       failure:failure
                                                                         checkIfTokenIsExpired:NO];

                    [self.operationQueue addOperation:moperation]; //5
                }                    failure: ^(NSError *error) {
                    failure(nil, error);
                }];
            }
            else {
                failure(operation, error); //6
            }
        }];
    }
  • //1: проверете http status code, ако 401 опитайте автоматично повторно упълномощаване.
  • //2: reauthorize е частен метод, който използва AFOAuthManager за опресняване на токена.
  • //3: В този случай сме преупълномощени успешно и искаме да изпратим отново копие от предишната заявка. Методът requestByAddingHeadersToRequest: просто копира всички полета на заглавката от предишната заявка.
  • //4: Създайте копие на предишната заявка, но този път последният параметър е false, защото не искаме повторна проверка! successBlock и failureBlock са същите като предишната заявка.
  • //5: Добавете операцията към опашката.
  • //6: Ако методът за преупълномощаване е неуспешен, просто извикайте блока за неуспех.
person IgnazioC    schedule 24.08.2015
comment
Това е фантастичен отговор! Любопитен съм: как бихте приложили метода reauthorizeWithSuccess:, за да гарантирате, че не повече от една заявка за опресняване на токени се задейства едновременно? По същия начин: ако сте в средата на опресняване на токени, не искате други заявки да се задействат с текущия, изтекъл токен. Какъв е лесният начин за прилагане на това? Спирането на опашката изглежда малко космато... - person Javier Soto; 25.08.2015
comment
Ако харесвате отговора, можете ли да гласувате за? :) Относно вашите въпроси, няма конкретна проверка за множество заявки. В моя проект няма начин да имам няколко заявки едновременно, така че за мен е добре. В противен случай ще предложа два подхода: 1. не правете нищо специално. Дори ако имате 3 обаждания успоредно и обновявате токена, ще получите 3 ненужни заявки, това голяма работа ли е? зависи от проекта. 2. Добавете флагова променлива (атомарна) и я поставете на true по време на задачата за опресняване на токена. Ако заявката ви е неуспешна и това булево значение е вярно, просто опитайте отново след 0,1 сек. - person IgnazioC; 25.08.2015

За съжаление не намерих рамка за решаване на този проблем, така че написах кратка обвивка около AFNetworking (ако някой се интересува, мога да публикувам в github) Логиката е да изпълните заявката и в случай на http отговор 401, опитайте да обновите токена за удостоверяване и когато е готово, за повторно изпълнение на предишната заявка.

person IgnazioC    schedule 22.08.2015
comment
Бихте ли го поставили в GitHub, моля? - person Miroslav Kuťák; 30.09.2015
comment
здравей IgnazioC, моля, дай пример Благодаря! - person manuelBetancurt; 07.04.2017


Бързо решение с Alamofire 4.0. Въз основа на протоколите RequestAdapter и RequestRetrier: пример връзка

person biloshkurskyi.ss    schedule 06.09.2018