Я столкнулся с той же проблемой при разработке моего бэкенда с Spring Boot и OAuth2. Проблема, с которой я столкнулся, заключалась в том, что если несколько устройств совместно использовали одни и те же токены, то, как только одно устройство обновляло токен, другое устройство было бы невежественным, и, короче говоря, оба устройства входили в безумие обновления токена. Мое решение состояло в том, чтобы заменить стандартную AuthenticationKeyGenerator
реализацию пользовательской реализацией, которая переопределяет DefaultAuthenticationKeyGenerator
и добавляет новый параметр client_instance_id
в смесь генератора ключей. Мои мобильные клиенты затем отправляют этот параметр, который должен быть уникальным при установке приложений (iOS или Android). Это не специальное требование, так как большинство мобильных приложений уже отслеживают экземпляр приложения в той или иной форме.
public class EnhancedAuthenticationKeyGenerator extends DefaultAuthenticationKeyGenerator {
public static final String PARAM_CLIENT_INSTANCE_ID = "client_instance_id";
private static final String KEY_SUPER_KEY = "super_key";
private static final String KEY_CLIENT_INSTANCE_ID = PARAM_CLIENT_INSTANCE_ID;
@Override
public String extractKey(final OAuth2Authentication authentication) {
final String superKey = super.extractKey(authentication);
final OAuth2Request authorizationRequest = authentication.getOAuth2Request();
final Map<String, String> requestParameters = authorizationRequest.getRequestParameters();
final String clientInstanceId = requestParameters != null ? requestParameters.get(PARAM_CLIENT_INSTANCE_ID) : null;
if (clientInstanceId == null || clientInstanceId.length() == 0) {
return superKey;
}
final Map<String, String> values = new LinkedHashMap<>(2);
values.put(KEY_SUPER_KEY, superKey);
values.put(KEY_CLIENT_INSTANCE_ID, clientInstanceId);
return generateKey(values);
}
}
который вы затем вводите аналогичным образом:
final JdbcTokenStore tokenStore = new JdbcTokenStore(mDataSource);
tokenStore.setAuthenticationKeyGenerator(new EnhancedAuthenticationKeyGenerator());
HTTP-запрос будет выглядеть примерно так
POST /oauth/token HTTP/1.1
Host: {{host}}
Authorization: Basic {{auth_client_basic}}
Content-Type: application/x-www-form-urlencoded
grant_type=password&username={{username}}&password={{password}}&client_instance_id={{instance_id}}
Преимущество использования этого подхода состоит в том, что, если клиент не отправляет client_instance_id
, будет создан ключ по умолчанию, и если предоставляется экземпляр, один и тот же ключ возвращается каждый раз для одного и того же экземпляра. Кроме того, ключ не зависит от платформы. Недостатком является то, что дайджест MD5 (используется внутри) вызывается два раза.