Beim Entwickeln meines Backends mit Spring Boot und OAuth2 bin ich auf dasselbe Problem gestoßen. Das Problem, auf das ich gestoßen bin, war, dass, wenn mehrere Geräte die gleichen Token gemeinsam nutzen, sobald ein Gerät das Token aktualisiert hat, das andere Gerät keine Ahnung hat und, um es kurz zu machen, beide Geräte in einen Token-Aktualisierungsrausch geraten sind. Meine Lösung bestand darin, den Standardwert AuthenticationKeyGenerator
durch eine benutzerdefinierte Implementierung zu ersetzen, die DefaultAuthenticationKeyGenerator
einen neuen Parameter client_instance_id
in der Schlüsselgeneratormischung überschreibt und hinzufügt . Meine mobilen Clients würden dann diesen Parameter senden, der für alle App-Installationen (iOS oder Android) eindeutig sein muss. Dies ist keine spezielle Anforderung, da die meisten mobilen Apps die Anwendungsinstanz bereits in irgendeiner Form verfolgen.
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);
}
}
welche du dann auf ähnliche weise spritzen würdest:
final JdbcTokenStore tokenStore = new JdbcTokenStore(mDataSource);
tokenStore.setAuthenticationKeyGenerator(new EnhancedAuthenticationKeyGenerator());
Die HTTP-Anfrage würde dann ungefähr so aussehen
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}}
Der Vorteil dieses Ansatzes besteht darin, dass client_instance_id
der Standardschlüssel generiert wird, wenn der Client keinen sendet. Wenn eine Instanz bereitgestellt wird, wird jedes Mal derselbe Schlüssel für dieselbe Instanz zurückgegeben. Außerdem ist der Schlüssel plattformunabhängig. Der Nachteil wäre, dass der MD5-Digest (intern verwendet) zweimal aufgerufen wird.