Registrierung

improve this page | report issue

Übersicht

Dieses Beispiel demonstriert einen angepassten Registrierungsprozess und eine intensivierte Autorisierung. Während dieses einmaligen Registrierungsprozesses muss der Benutzer seinen Benutzernamen und sein Kennwort eingeben und einen PIN-Code definieren.

Voraussetzung: Sie müssen die Lernprogramme ExternalizableSecurityCheck und Intensivierung durcharbeiten.

Fahren Sie mit folgenden Abschnitten fort:

Anwendungsablauf

  • Wenn die Anwendung zum ersten Mal (d. h. vor der Registrierung) startet, zeigt sie die Benutzerschnittstelle mit den beiden Schaltflächen Get public data (Öffentliche Daten abrufen) und Enroll (Registrieren).
  • Wenn der Benutzer auf die Schaltfläche Enroll tippt, um die Registrierung zu starten, wird ein Anmeldeformular angezeigt. Der Benutzer wird aufgefordert, einen PIN-Code festzulegen.
  • Wenn sich der Benutzer erfolgreich registriert hat, enthält die Benutzerschnittstelle die vier Schaltflächen Get public data (Öffentliche Daten abrufen), Get balance (Kontostand abrufen), Get transactions (Transaktionen abrufen) und Logout (Abmelden). Der Benutzer kann auf alle vier Schaltflächen zugreifen, ohne den PIN-Code einzugeben.
  • Wenn die Anwendung zum zweiten Mal (d. h. nach der Registrierung) gestartet wird, enthält die Benutzerschnittstelle weiter alle vier Schaltflächen. Tippt der Benutzer jedoch auf die Schaltfläche Get transactions*, muss er den PIN-Code eingeben.

Nach drei ungültigen Eingabeversuchen für den PIN-Code wird der Benutzer aufgefordert, sich erneut mit einem Benutzernamen und einem Kennwort zu authentifizieren und den PIN-Code zurückzusetzen.

Daten in persistenten Attributen speichern

Sie haben die Möglichkeit, geschützte Daten im PersistentAttributes-Objekt zu speichern. Dieses Objekt ist ein Container für angepasste Attribute eines registrierten Clients. Auf das Objekt kann eine Sicherheitsprüfungsklasse oder eine Adapterressourcenklasse zugreifen.

In der bereitgestellten Beispielanwendung wird das PersistentAttributes-Objekt in der Adapterressourcenklasse verwendet, um den PIN-Code zu speichern.

  • Die Ressource setPinCode fügt das Attribut pinCode hinzu und ruft die Methode AdapterSecurityContext.storeClientRegistrationData() auf, um die Änderungen zu speichern.

    @POST
    @OAuthSecurity(scope = "setPinCode")
    @Path("/setPinCode/{pinCode}")
      
    public Response setPinCode(@PathParam("pinCode") String pinCode){
    		ClientData clientData = adapterSecurityContext.getClientRegistrationData();
    		clientData.getProtectedAttributes().put("pinCode", pinCode);
    		adapterSecurityContext.storeClientRegistrationData(clientData);
    		return Response.ok().build();
    }
    

    Hier hat users einen Schlüssel mit der Bezeichnung EnrollmentUserLogin, der wiederum das AuthenticatedUser-Objekt enthält.

  • Die Ressource unenroll löscht das Attribut pinCode und ruft die Methode AdapterSecurityContext.storeClientRegistrationData() auf, um die Änderungen zu speichern.

    @DELETE
    @OAuthSecurity(scope = "unenroll")
    @Path("/unenroll")
      
    public Response unenroll(){
    		ClientData clientData = adapterSecurityContext.getClientRegistrationData();
    		if (clientData.getProtectedAttributes().get("pinCode") != null){
    			clientData.getProtectedAttributes().delete("pinCode");
    			adapterSecurityContext.storeClientRegistrationData(clientData);
    		}
    		return Response.ok().build();
    }
    

Sicherheitsüberprüfungen

Das Registrierungsbeispiel enthält drei Sicherheitsüberprüfungen:

EnrollmentUserLogin

Die Sicherheitsüberprüfung EnrollmentUserLogin schützt die Ressource setPinCode, sodass nur authentifizierte Benutzer einen PIN-Code festlegen können. Diese Sicherheitsüberprüfung soll eine kurze Ablaufzeit haben, da sie nur für die “Ersterfahrung” des Benutzers bestimmt ist. Die Sicherheitsüberprüfung stimmt mit der Überprüfung UserLogin überein, die im Lernprogramm UserAuthenticationSecurityCheck erläutert ist, verfügt jedoch zusätzlich über die Methoden isLoggedIn und getRegisteredUser.
Die Methode isLoggedIn gibt true zurück, wenn die Sicherheitsüberprüfung erfolgreich war (SUCCESS). Andernfalls gibt sie false zurück.
Die Methode getRegisteredUser gibt den authentifizierten Benutzer zurück.

public boolean isLoggedIn(){
    return getState().equals(STATE_SUCCESS);
}
public AuthenticatedUser getRegisteredUser() {
    return registrationContext.getRegisteredUser();
}

EnrollmentPinCode

Die Sicherheitsüberprüfung EnrollmentPinCode schützt die Ressource Get transactions und ist mit der Sicherheitsüberprüfung PinCodeAttempts vergleichbar, die im Lernprogramm CredentialsValidationSecurityCheck implementieren erläutert ist. Beide Überprüfungen unterscheiden sich nur in einigen wenigen Punkten.

In dem in diesem Lernprogramm verwendeten Beispiel ist EnrollmentPinCode abhängig von EnrollmentUserLogin. Nach erfolgreicher Anmeldung bei EnrollmentUserLogin wird der Benutzer nur aufgefordert, einen PIN-Code einzugeben.

@SecurityCheckReference
private transient EnrollmentUserLogin userLogin;

Wenn die Anwendung zum ersten Mal gestartet wird und der Benutzer erfolgreich registriert wurde, muss er auf die Ressource Get transactions zugreifen können, ohne den gerade festgelegten PIN-Code einzugeben. Die Methode authorize verwendet zu diesem Zweck die Methode EnrollmentUserLogin.isLoggedIn, um zu überprüfen, ob der Benutzer angemeldet ist. Das bedeutet, dass der Benutzer auf Get transactions zugreifen kann, solange EnrollmentUserLogin nicht abgelaufen ist.

@Override

public void authorize(Set<String> scope, Map<String, Object> credentials, HttpServletRequest request, AuthorizationResponse response) {
    if (userLogin.isLoggedIn()){
        setState(STATE_SUCCESS);
        response.addSuccess(scope, userLogin.getExpiresAt(), getName());
    }
}

Wenn der Benutzer dreimal vergeblich versucht, den richtigen PIN-Code einzugeben, wird in diesem Lernprogramm das Attribut pinCode gelöscht, bevor der Benutzer aufgefordert wird, sich mit seinem Benutzernamen und seinem Kennwort zu authentifizieren und den PIN-Code zurückzusetzen.

@Override

public void authorize(Set<String> scope, Map<String, Object> credentials, HttpServletRequest request, AuthorizationResponse response) {
    PersistentAttributes attributes = registrationContext.getRegisteredProtectedAttributes();
    if (userLogin.isLoggedIn()){
        setState(STATE_SUCCESS);
        response.addSuccess(scope, userLogin.getExpiresAt(), getName());
    } else {
        super.authorize(scope, credentials, request, response);
        if (getState().equals(STATE_BLOCKED)){
            attributes.delete("pinCode");
        }
    }
}

Die Methode validateCredentials ist die gleiche wie in der Sicherheitsüberprüfung PinCodeAttempts, nur dass hier die Berechtigungsnachweise mit dem gespeicherten Attribut pinCode verglichen werden.

@Override

protected boolean validateCredentials(Map<String, Object> credentials) {
    PersistentAttributes attributes = registrationContext.getRegisteredProtectedAttributes();
    if(credentials!=null &&  credentials.containsKey("pin")){
        String pinCode = credentials.get("pin").toString();

        if(pinCode.equals(attributes.get("pinCode"))){
            errorMsg = null;
            return true;
        }
        else {
            errorMsg = "The pin code is not valid. Hint: " + attributes.get("pinCode");
        }
    }
    else{
        errorMsg = "The pin code was not provided.";
    }
    // In allen anderen Fällen sind Berechtigungsnachweise nicht gültig.
    return false;
}

IsEnrolled

Die Sicherheitsüberprüfung IsEnrolled schützt Folgendes:

  • Die Ressource getBalance, sodass nur registrierte Benutzer den Kontostand sehen können
  • Die Ressource transactions, sodass nur registrierte Benutzer die Transaktionen abrufen können
  • Die Ressource unenroll, sodass der PIN-Code (pinCode) nur gelöscht werden kann, wenn er zuvor festgelegt wurde

Sicherheitsüberprüfung erstellen

Erstellen Sie einen Java-Adapter und fügen Sie eine Java-Klasse mit der Bezeichnung IsEnrolled hinzu, die ExternalizableSecurityCheck erweitert.

public class IsEnrolled  extends ExternalizableSecurityCheck{
    protected void initStateDurations(Map<String, Integer> durations) {}

    public void authorize(Set<String> scope, Map<String, Object> credentials, HttpServletRequest request, AuthorizationResponse response) {}

    public void introspect(Set<String> scope, IntrospectionResponse response) {}
}

Konfigurationsklasse IsEnrolledConfig

Erstellen Sie eine Konfigurationsklasse IsEnrolledConfig, die ExternalizableSecurityCheckConfig erweitert:

public class IsEnrolledConfig extends ExternalizableSecurityCheckConfig {

    public int successStateExpirationSec;

    public IsEnrolledConfig(Properties properties) {
        super(properties);
        successStateExpirationSec = getIntProperty("expirationInSec", properties, 8000);
    }
}

Fügen Sie die Methode createConfiguration zur Klasse IsEnrolled hinzu:

public class IsEnrolled  extends ExternalizableSecurityCheck{
    @Override
    public SecurityCheckConfiguration createConfiguration(Properties properties) {
        return new IsEnrolledConfig(properties);
    }
}

Methode initStateDurations

Setzen Sie die Dauer des Erfolgszustands (SUCCESS) auf successStateExpirationSec:

@Override
protected void initStateDurations(Map<String, Integer> durations) {
    durations.put (SUCCESS_STATE, ((IsEnrolledConfig) config).successStateExpirationSec);
}

Methode authorize

Das Codebeispiel überprüft lediglich, ob der Benutzer registriert ist, und gibt je nach Ergebnis “sucess” oder “failure” zurück:

public void authorize(Set<String> scope, Map<String, Object> credentials, HttpServletRequest request, AuthorizationResponse response) {
    PersistentAttributes attributes = registrationContext.getRegisteredProtectedAttributes();
    if (attributes.get("pinCode") != null){
        setState(SUCCESS_STATE);
        response.addSuccess(scope, getExpiresAt(), this.getName());
    } else  {
        setState(STATE_EXPIRED);
        Map <String, Object> failure = new HashMap<String, Object>();
        failure.put("failure", "User is not enrolled");
        response.addFailure(getName(), failure);
    }
}
  • Wenn das Attribut pinCode vorhanden ist:

  • wird der Zustand mit der Methode setState auf SUCCESS (Erfolg) gesetzt.
  • wird der Erfolg mit der Methode addSuccess zum Antwortobjekt hinzugefügt.

  • Wenn das Attribut pinCode nicht vorhanden ist:

  • wird der Zustand mit der Methode setState auf EXPIRED (Abgelaufen) gesetzt.
  • wird der Fehlschlag mit der Methode addFailure zum Antwortobjekt hinzugefügt.


Die Sicherheitsüberprüfung IsEnrolled ist abhängig von EnrollmentUserLogin:

@SecurityCheckReference
private transient EnrollmentUserLogin userLogin;

Definieren Sie den aktiven Benutzer, indem Sie den folgenden Code hinzufügen:

public void authorize(Set<String> scope, Map<String, Object> credentials, HttpServletRequest request, AuthorizationResponse response) {
    PersistentAttributes attributes = registrationContext.getRegisteredProtectedAttributes();
    if (attributes.get("pinCode") != null){
        // Ist zurzeit ein Benutzer aktiv?
        if (!userLogin.isLoggedIn()){
            // Wenn nicht, hier einen festlegen
            authorizationContext.setActiveUser(userLogin.getRegisteredUser());
        }
        setState(SUCCESS_STATE);
        response.addSuccess(scope, getExpiresAt(), this.getName());
    } else  {
        setState(STATE_EXPIRED);
        Map <String, Object> failure = new HashMap<String, Object>();
        failure.put("failure", "User is not enrolled");
        response.addFailure(getName(), failure);
    }
}

Die Ressource transactions empfängt anschließend das aktuelle AuthenticatedUser-Objekt, um den Anzeigenamen zu präsentieren:

@GET
@Produces(MediaType.TEXT_PLAIN)
@OAuthSecurity(scope = "transactions")
@Path("/transactions")

public String getTransactions(){
  AuthenticatedUser currentUser = securityContext.getAuthenticatedUser();
  return "Transactions for " + currentUser.getDisplayName() + ":\n{'date':'12/01/2016', 'amount':'19938.80'}";
}

Weitere Informationen zu securityContext finden Sie im Abschnitt Sicherheits-API des Lernprogramms für Java-Adapter.

Fügen Sie den registrierten Benutzer zum Antwortobjekt hinzu. Fügen Sie dafür folgenden Code hinzu:

public void authorize(Set<String> scope, Map<String, Object> credentials, HttpServletRequest request, AuthorizationResponse response) {
    PersistentAttributes attributes = registrationContext.getRegisteredProtectedAttributes();
    if (attributes.get("pinCode") != null){
        // Ist zurzeit ein Benutzer aktiv?
        if (!userLogin.isLoggedIn()){
            // Wenn nicht, hier einen festlegen
            authorizationContext.setActiveUser(userLogin.getRegisteredUser());
        }
        setState(SUCCESS_STATE);
        response.addSuccess(scope, getExpiresAt(), getName(), "user", userLogin.getRegisteredUser());
    } else  {
        setState(STATE_EXPIRED);
        Map <String, Object> failure = new HashMap<String, Object>();
        failure.put("failure", "User is not enrolled");
        response.addFailure(getName(), failure);
    }
}

In umserem Beispielcode verwendet die Methode handleSuccess des Abfrage-Handlers von IsEnrolled das Benutzerobjekt, um den Anzeigenamen zu präsentieren.

Beispielanwendung für Registrierung

Beispielanwendungen

Sicherheitsüberprüfung

Die Sicherheitsüberprüfungen EnrollmentUserLogin, EnrollmentPinCode und IsEnrolled sind im SecurityChecks-Projekt unter dem Maven-Projekt für Registrierung verfügbar. Klicken Sie hier, um das Maven-Projekt für Sicherheitsüberprüfungen herunterzuladen.

Anwendungen

Beispielanwendungen sind für iOS (Swift), Android, Cordova und das World Wide Web verfügbar.

Verwendung des Beispiels

Anweisungen finden Sie in der Datei README.md zum Beispiel.

Inclusive terminology note: The Mobile First Platform team is making changes to support the IBM® initiative to replace racially biased and other discriminatory language in our code and content with more inclusive language. While IBM values the use of inclusive language, terms that are outside of IBM's direct influence are sometimes required for the sake of maintaining user understanding. As other industry leaders join IBM in embracing the use of inclusive language, IBM will continue to update the documentation to reflect those changes.
Last modified on February 27, 2020