2016-10-29 2 views
0

Ich habe eine mandantenfähige REST-App. Wenn ein neuer Benutzer zuerst versucht, auf meine Anwendung zuzugreifen (und vorausgesetzt, der Administrator hat der App bereits die Berechtigung für sein Verzeichnis erteilt), erstelle ich eine Benutzerzeile in meiner Benutzertabelle und speichere deren Name/E-Mail und andere Felder. Ich führe dies im TokenValidated-Event von JwtBearerEvents durch.Erstellen eines neuen Benutzers in ADAL TokenValidated führt zu Duplikaten

Leider bin ich am Ende mit mehreren User-Zeilen, die versuchen, eingefügt werden wegen der gleichzeitigen (parallel Anfrage) meine Web-API zu schlagen. Ich mache eine einfache SQL-Abfrage für den Benutzer nach ObjectId und dann erstellen Sie bei Bedarf. Dies ist kein Threadsicher. Ich habe versucht, es in eine SQL-Transaktion zu verpacken, aber die Auswahl blockiert nicht, und ich bin mir nicht sicher, ob EF Core die Art der Sperrung durchführen kann, die ich brauche, um andere Auswahlen zu blockieren.

Ich basiere meinen Code von der TailSpin PnP und sie führen die gleiche Logik auch hier. Meine Vermutung ist, dass ihre Standortlogik einen einzelnen Aufruf der WEB-API zuerst als Teil des Anmelde-/Anmeldeprozesses erzwingt, wo der neue Benutzer erstellt wird, wenn er nicht existiert. In meinem Flow wird die REST-API sofort mit mehreren HTTP-GETs abgefangen und ich muss nur das Bearer-Token in den Headern validieren und ADAL zwischenspeichern.

Abgesehen von der Änderung meiner Clientlogik und dem Erzwingen des ersten Aufrufs von API zu einem einzelnen HTTP-GET, wie kann ich sonst in einer REST-Welt arbeiten? Ich kann SESSION-Logik nicht verwenden, um andere Anrufe in derselben Sitzung zu blockieren. Ich bin nicht sicher, wie ich eine Sperre über den ganzen Server durchführen kann (was nur funktioniert, wenn es einen Server gibt). Ich könnte den DB-Layer verwenden, um eine Schreibsperre zu halten, aber das scheint schmutzig. Vielleicht gibt es einen besseren Ort, um die neue Benutzerlogik zu erstellen? Gibt es eine andere Möglichkeit für mich, eine einmalige atomare Operation sicher durchzuführen?

Antwort

0

Basierend auf der Beschreibung scheint es, dass Sie den Benutzerdatensatz (Anmeldung) erstellt haben, wenn die Benutzer die REST-API aufrufen und nachdem das Token validiert wurde.

Um das Duplikat-Datensatzproblem zu beheben, besteht eine Möglichkeit darin, den Anmeldevorgang von der Token-Validierung zu trennen, genauso wie das Codebeispiel TailSpin PnP. Beispielsweise können wir den Token-Handler anpassen, um zu überprüfen, ob sich die Benutzer anmelden, und die Benutzeroberfläche für die Benutzeranmeldung bereitzustellen.

Eine andere Möglichkeit besteht darin, dass Sie die Benutzer der Reihe nach mit der Sperre einfügen können. Zum Beispiel ist hier der Code für Ihre Referenz:

private Task tokenValidated(TokenValidatedContext context) 
{ 
    lock (obj) 
    { 
     //query db and insert users here 
    } 
    return Task.Delay(0); 

} 
+0

Ich dachte über die Verwendung eines Schlosses, war aber unsicher, was zu sperren. So oder so schützt es mich nur, wenn es auf einem einzigen Server läuft. Was würdest du als Sperrobjekt verwenden? – Frank

+0

Ich benutze ein Objekt, das in der 'Startup'-Klasse erstellt wurde, das für die Einzelinstanz-App funktionieren sollte. Eine weitere einfache Möglichkeit, um das Einfügen duplizierter Datensätze zu verhindern, ist die Einstellung des richtigen Primärschlüssels für die Tabelle ** User **. Zum Beispiel können Sie die ** ObjectId ** als Primärschlüssel festlegen. –

+0

Der fehlende Schlüssel in der DB war ein Bereitstellungsproblem, das sinnvollerweise behoben wurde. Ich habe den Code geschrieben, um eine Insert-Exception zu behandeln und in diesem Fall von "Create" auf "Get" zu wechseln, so dass Autoscale immer noch funktionieren kann (mehrere Web-Service-Instanzen). Fühlt sich immer noch falsch an, aber für den Moment. – Frank

Verwandte Themen