Как автоматически обновить токен с истекшим сроком действия с помощью 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: повторная авторизация — это закрытый метод, который использует AFOAuthManager для обновления токена.
  • //3: В этом случае мы успешно прошли повторную авторизацию и хотим повторно отправить копию предыдущего запроса. Метод requestByAddingHeadersToRequest: просто копирует все поля заголовка из предыдущего запроса.
  • //4: Создадим копию предыдущего запроса, но на этот раз последний параметр будет ложным, потому что нам не нужна повторная проверка! 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