Мы используем Retrofit в нашем Android-приложении для связи с защищенным сервером OAuth2. Все отлично работает, мы используем RequestInterceptor для включения токена доступа при каждом вызове. Однако будут времена, когда срок действия токена доступа истечет, и токен необходимо обновить. Когда срок действия токена истечет, следующий вызов вернется с неавторизованным HTTP-кодом, поэтому его легко отслеживать. Мы могли бы изменить каждый вызов Retrofit следующим образом: в обратном вызове сбоя проверьте код ошибки, если он равен Unauthorized, обновите токен OAuth, затем повторите вызов Retrofit. Однако для этого необходимо изменить все вызовы, что не является легко обслуживаемым и хорошим решением. Есть ли способ сделать это, не изменяя все вызовы Retrofit?
157
Ответы:
Пожалуйста, не используйте
Interceptors
для проверки подлинности.В настоящее время лучшим подходом к обработке аутентификации является использование нового
Authenticator
API, разработанного специально для этой цели .OkHttp будет автоматически задать
Authenticator
учетные данные , когда ответ401 Not Authorised
Повторная отправка последний запрос не удалось с ними.Прикрепите
Authenticator
к такOkHttpClient
же, как вы делаете сInterceptors
Используйте этот клиент при создании вашего
Retrofit
RestAdapter
источник
TokenAuthenticator
зависит отservice
класса.service
Класс зависит отOkHttpClient
экземпляра. Для созданияOkHttpClient
мне нужноTokenAuthenticator
. Как я могу разорвать этот цикл? Два разныхOkHttpClient
с? У них будут разные пулы соединений ...Если вы используете Retrofit > =,
1.9.0
то вы можете использовать новый перехватчик OkHttp , который был представлен в . Вы хотели бы использовать перехватчик приложений , который позволяет вам .OkHttp 2.2.0
retry and make multiple calls
Ваш перехватчик может выглядеть примерно так:
После того, как вы определите свой
Interceptor
, создайтеOkHttpClient
и добавьте перехватчик в качестве перехватчика приложения .И, наконец, используйте это
OkHttpClient
при созданииRestAdapter
.Предупреждение: как
Jesse Wilson
(с площади) здесь упоминается , это опасное количество энергии.С учетом сказанного, я определенно думаю, что сейчас это лучший способ справиться с чем-то подобным. Если у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь спрашивать в комментарии.
источник
Если у вас есть, скажем, Retrofit,
TokenService
который вам нужен,Authenticator
но вы бы хотели установить только тот, для которогоOkHttpClient
вы можете использоватьTokenServiceHolder
как зависимостьTokenAuthenticator
. Вы должны будете поддерживать ссылку на него на уровне приложения (singleton). Это легко, если вы используете Dagger 2, иначе просто создайте поле класса внутри вашего Приложения.В
TokenAuthenticator.java
В
TokenServiceHolder.java
:Настройка клиента:
Если вы используете Dagger 2 или аналогичную инфраструктуру внедрения зависимостей, в ответах на этот вопрос есть несколько примеров.
источник
TokenService
создается класс?refreshToken()
отservice.refreshToken().execute();
. Не в состоянии найти его реализацию нигде.Использование
TokenAuthenticator
ответа типа @theblang является правильным способом обработкиrefresh_token
.Вот мой инструмент (я использую Kotlin, Dagger, RX, но вы можете использовать эту идею для реализации в вашем случае)
TokenAuthenticator
Для предотвращения цикла зависимостей типа комментария @Brais Gabin, я создаю 2 интерфейса:
и
AccessTokenWrapper
классAccessToken
классМой перехватчик
Наконец, добавьте
Interceptor
иAuthenticator
к вашемуOKHttpClient
при создании службы PotoAuthApiдемонстрация
https://github.com/PhanVanLinh/AndroidMVPKotlin
Заметка
Аутентификатор потокаgetImage()
возврата API 401 код ошибкиauthenticate
метод внутриTokenAuthenticator
будет уволенnoneAuthAPI.refreshToken(...)
называетсяnoneAuthAPI.refreshToken(...)
ответа -> новый токен добавит в шапкуgetImage()
будет вызываться AUTO с новым заголовком (HttpLogging
НЕ будет регистрировать этот вызов) (intercept
внутри неAuthInterceptor
будет вызываться )Если
getImage()
ошибка 401 все еще не сработала,authenticate
метод внутриTokenAuthenticator
будет вызывать ОПЯТЬ и СНОВА, а затем будет много раз выдавать ошибку о вызове метода (java.net.ProtocolException: Too many follow-up requests
). Вы можете предотвратить это, посчитав ответ . Например, если выreturn null
вauthenticate
после 3 -х раз повторить,getImage()
будет закончить иreturn response 401
Если
getImage()
ответ успешен =>, мы приведем результат в обычном режиме (как вы звонитеgetImage()
без ошибок)Надеюсь, это поможет
источник
Я знаю эту старую ветку, но на всякий случай кто-то наткнулся на нее.
Я столкнулся с той же проблемой, но я хотел создать только один OkHttpClient, потому что я не думаю, что мне нужен другой только для самого TokenAuthenticator, я использовал Dagger2, поэтому я в итоге предоставил класс обслуживания, как Lazy внедрен в TokenAuthenticator, вы можете прочитать больше о Lazy инъекции в dagger 2 здесь , но это все равно что сказать Dagger НЕ идти и создавать сервис, необходимый для TokenAuthenticator сразу.
Вы можете обратиться к этой теме SO за примером кода: Как разрешить циклическую зависимость, все еще используя Dagger2?
источник
Вы можете попробовать создать базовый класс для всех ваших загрузчиков, в котором вы сможете перехватить конкретное исключение и затем действовать так, как вам нужно. Сделайте так, чтобы все ваши различные загрузчики расширялись от базового класса, чтобы распространить поведение.
источник
После долгих исследований я настроил клиент Apache для обработки обновления AccessToken For Retrofit, в котором вы отправляете маркер доступа в качестве параметра.
Инициируйте свой адаптер с постоянным клиентом cookie
Cookie Постоянный клиент, который поддерживает куки для всех запросов и проверяет каждый ответ на запрос, если это неавторизованный доступ ERROR_CODE = 401, обновляет токен доступа и отзывает запрос, иначе просто обрабатывает запрос.
источник
Использование одного перехватчика (инъекция токена) и одного аутентификатора (операции обновления) делают эту работу, но:
У меня также была проблема двойного вызова: первый вызов всегда возвращал 401 : токен не был введен при первом вызове (перехватчик), и был вызван аутентификатор: было сделано два запроса.
Исправление состояло в том, чтобы просто отразить запрос на сборку в Interceptor:
ПЕРЕД:
ПОСЛЕ:
В ОДНОМ БЛОКЕ:
Надеюсь, поможет.
Изменить: я не нашел способ избежать первого вызова всегда возвращать 401, используя только аутентификатор и без перехватчика
источник
Всем, кто хотел бы разрешить параллельные / параллельные вызовы при обновлении токена. Вот обходной путь
источник