Juni 2019

Band 34, Nummer 6

[ASP.NET Core 3.0]

KI-gestützte biometrische Sicherheit in ASP.NET Core

Von Stefano Tempesta

Dieser zweiteilige Artikel stellt das richtlinienbasierte Autorisierungsmodell in ASP.NET Core 3 vor, das darauf abzielt, die Autorisierungslogik von den zugrunde liegenden Benutzerrollen zu entkoppeln. Er stellt ein konkretes Beispiel für diesen Autorisierungsvorgang vor, der auf biometrischen Informationen wie Gesichts- oder Spracherkennung basiert. In diesem Fall wird der Zugang zu einem Gebäude eingeschränkt, wenn ein unbefugtes Eindringen erkannt wird. Der Schweregrad des Eindringens wird von einem in Azure Machine Learning integrierten Anomalieerkennungsdienst bewertet.

Zugang zum Standort

Der Kontext ist ein extrem gesicherter Standort. Denken Sie dabei an ein Militärgelände, ein Krankenhaus oder ein Datencenter. Der Zugang ist mit einigen Einschränkungen auf autorisierte Personen beschränkt. Die folgenden Schritte beschreiben den Sicherheitsablauf, der an der Tür jedes Gebäudes durchgesetzt wird, um Personen einzuchecken:

  1. Eine Person, die den Zutritt zu einem Gebäude verlangt, zieht ihren Zugangsausweis durch den Kartenleser an der Tür.
  2. Kameras erkennen Bewegungen und erfassen Gesicht und Körper der Person. Dies sollte beispielsweise die Verwendung eines gedruckten Fotos verhindern, um die Kamera mit einer reinen Gesichtserkennung zu täuschen.
  3. Der Kartenleser und die Kameras sind als IoT-Geräte (Internet der Dinge) registriert und übertragen die aufgezeichneten Daten an Azure IoT Hub.
  4. Microsoft Cognitive Services vergleicht die Person mit einer Datenbank von Personen, die berechtigt sind, das Gebäude zu betreten.
  5. Ein Autorisierungsfluss gleicht die von den IoT-Geräten erfassten biometrischen Informationen mit der Identität der Person auf dem Zugangsausweis ab.
  6. Ein Azure Machine Learning Service wird aufgerufen, um das Risiko der Zugangsanforderung zu beurteilen und festzustellen, ob es sich um einen unbefugten Eindringversuch handelt.
  7. Die Autorisierung erfolgt über eine ASP.NET Core-Web-API, indem nach spezifischen Richtlinienanforderungen des in den vorherigen Schritten definierten Profils gesucht wird.

Bei einem Konflikt zwischen der erkannten Identität der Person und dem Zugangsausweis wird der Zugang zum Standort sofort gesperrt. Andernfalls wird der Zugangsfluss fortgesetzt, indem überprüft wird, ob eine der folgenden Anomalien aufgetreten ist:

  • Atypische Häufigkeit des Zugangs zum Gebäude.
  • Ob die Person das Gebäude zuvor verlassen hat (Checkout).
  • Anzahl der erlaubten Zutritte pro Tag.
  • Ob die Person im Dienst ist.
  • Relevanz des Gebäudes (Sie möchten den Zugang zu einer Kantine möglicherweise nicht einschränken, aber eine strengere Richtlinie für den Zugang zu einem Serverdatencenter durchsetzen).
  • Ob die Person jemanden oder etwas mitbringt.
  • Frühere Vorkommen ähnlicher Zugangstypologien für das gleiche Gebäude.
  • In der Vergangenheit gemessene Risikostufenänderungen.
  • Anzahl der in der Vergangenheit erkannten Eindringversuche.

Der Anomalieerkennungsdienst wird in Azure Machine Learning ausgeführt und gibt eine Bewertung zurück, ausgedrückt als Wahrscheinlichkeit, dass der Zugriff eine Abweichung vom Standard ist. Die Bewertung wird in einem Bereich zwischen Null und Eins ausgedrückt, wobei Null „kein Risiko erkannt“ bedeutet (alles OK, volle Vertrauenswürdigkeit), und Eins „roten Alarm“ auslöst, bei dem der Zugang sofort blockiert wird! Die Risikostufe jedes Gebäudes bestimmt den Schwellenwert, der als akzeptabel erachtet wird, um den Zugang zum Gebäude für jeden Wert größer als Null zu ermöglichen.

Autorisierung in ASP.NET Core

ASP.NET Core bietet eine einfache deklarative Autorisierungsrolle und ein umfassendes richtlinienbasiertes Modell. Die Autorisierung wird in Anforderungen ausgedrückt, und Handler bewerten die Ansprüche eines Benutzers anhand dieser Anforderungen. Um Benutzern den Zugang zu einem Standort zu ermöglichen, beschreibe ich, wie benutzerdefinierte Richtlinienanforderungen und deren Autorisierungshandler generiert werden können. Weitere Informationen zum Autorisierungsmodell in ASP.NET Core finden Sie in der Dokumentation unter bit.ly/2UYZaJh.

Wie bereits erwähnt, besteht ein benutzerdefinierter richtlinienbasierter Autorisierungsmechanismus aus Anforderungen und (typischerweise) einem Autorisierungshandler. Die Gewährung des Zugangs zu einem Gebäude besteht aus dem Aufruf einer API, die die Eingangstür entriegelt. IoT-Geräte übertragen biometrische Informationen an einen Azure IoT Hub, der wiederum den Verifizierungsworkflow auslöst, indem er die Standort-ID bereitstellt, eine eindeutige Bezeichnung für den Standort. Die POST-Methode der Web-API gibt einfach einen HTTP-Code 200 und eine JSON-Nachricht mit dem Benutzernamen und der Standort-ID zurück, wenn die Autorisierung erfolgreich ist. Andernfalls wird der erwartete HTTP-Fehlercode 401 für unbefugten Zugang ausgegeben. Aber schön der Reihe nach: Ich beginne mit der Startup-Klasse der Web-API, insbesondere mit der ConfigureServices-Methode, die die Anweisungen zur Konfiguration der notwendigen Dienste für die Ausführung der ASP.NET Core-Anwendung enthält. Die Autorisierungsrichtlinien werden durch Aufrufen der AddAuthorization-Methode für das services-Objekt hinzugefügt. Die AddAuthorization-Methode akzeptiert eine Sammlung von Richtlinien, die von der API-Funktion verarbeitet werden muss, wenn der Aufruf für die Autorisierung der Ausführung erfolgt. Ich benötige in diesem Fall nur eine Richtlinie, die ich „AuthorizedUser“ nenne. Diese Richtlinie enthält jedoch mehrere zu erfüllende Anforderungen, die die biometrischen Merkmale einer Person widerspiegeln, die ich überprüfen möchte: Gesicht, Körper und Stimme. Die drei Anforderungen werden jeweils durch eine bestimmte Klasse dargestellt, die die IAuthorizationRequirement-Schnittstelle implementiert, wie in Abbildung 1 gezeigt. Bei der Auflistung der Anforderungen für die AuthorizedUser-Richtlinie gebe ich auch die Vertrauensstufe an, die zur Erfüllung der Anforderung erforderlich ist. Wie ich bereits erwähnt habe, drückt dieser Wert (zwischen Null und Eins) die Genauigkeit der Identifizierung des jeweiligen biometrischen Attributs aus. Ich werde später darauf zurückkommen, wenn ich mit die biometrische Erkennung mit Cognitive Services untersuche.

Abbildung 1: Konfiguration der Autorisierungsanforderungen in der Web-API

public void ConfigureServices(IServiceCollection services)
{
  var authorizationRequirements = new List<IAuthorizationRequirement>
  {
    new FaceRecognitionRequirement(confidence: 0.9),
    new BodyRecognitionRequirement(confidence: 0.9),
    new VoiceRecognitionRequirement(confidence: 0.9)
  };
  services
    .AddAuthorization(options =>
    {
      options.AddPolicy("AuthorizedUser", policy => policy.Requirements =
        authorizationRequirements);
    })

Die AuthorizedUser-Autorisierungsrichtlinie enthält mehrere Autorisierungsanforderungen, und alle Anforderungen müssen erfüllt sein, damit die Richtlinienbewertung erfolgreich ist. Mit anderen Worten: Mehrere Autorisierungsanforderungen, die einer einzigen Autorisierungsrichtlinie hinzugefügt werden, werden auf UND-Basis verarbeitet.

Die drei Richtlinienanforderungen, die ich in der Lösung implementiert habe, sind alle Klassen, die die IAuthorizationRequirement-Schnittstelle implementieren. Diese Schnittstelle ist tatsächlich leer, d.h. sie diktiert nicht die Implementierung einer Methode. Ich habe die drei Anforderungen konsistent implementiert, indem ich eine öffentliche ConfidenceScore-Eigenschaft angegeben habe, um den erwarteten Grad an Vertrauen zu erfassen, den die Erkennungs-API erfüllen sollte, um diese Anforderung als erfolgreich zu betrachten. Die FaceRecognitionRequirement-Klasse sieht folgendermaßen aus:

public class FaceRecognitionRequirement : IAuthorizationRequirement
{
  public double ConfidenceScore { get; }
  public FaceRecognitionRequirement(double confidence) =>
    ConfidenceScore = confidence;
}

Ebenso werden die anderen Anforderungen an die Körper- und Spracherkennung in den Klassen BodyRecognitionRequirement bzw. VoiceRecognitionRequirement implementiert.

Die Autorisierung zum Ausführen einer Web-API-Aktion wird über das Authorize-Attribut gesteuert. Im einfachsten Fall beschränkt das Anwenden von AuthorizeAttribute auf einen Controller oder eine Aktion den Zugang zu diesem Controller oder dieser Aktion auf einen authentifizierten Benutzer. Die Web-API, die den Zugang zu einem Standort steuert, stellt einen einzigen Zugangscontroller bereit, der nur die Post-Aktion enthält. Diese Aktion wird autorisiert, wenn alle Anforderungen der angegebenen Richtlinie „AuthorizedUser“ erfüllt sind:

[ApiController]
public class AccessController : ControllerBase
{
  [HttpPost]
  [Authorize(Policy = "AuthorizedUser")]
  public IActionResult Post([FromBody] string siteId)
  {
    var response = new
    {
      User = HttpContext.User.Identity.Name,
      SiteId = siteId
    };
    return new JsonResult(response);
  }
}

Jede Anforderung wird von einem Autorisierungshandler (wie dem in Abbildung 2 gezeigten) verwaltet, der für die Auswertung einer Richtlinienanforderung verantwortlich ist. Sie können wählen, ob Sie einen einzelnen Handler für alle Anforderungen oder separate Handler für jede einzelne Anforderung verwenden möchten. Dieser letztgenannte Ansatz ist flexibler, da er es Ihnen ermöglicht, einen Gradienten von Berechtigungsanforderungen zu konfigurieren, den Sie einfach in der Startup-Klasse konfigurieren können. Die Handler für Gesicht, Körper und Stimme erweitern die abstrakte Klasse AuthorizationHandler<TRequirement>, wobei TRequirement die zu verarbeitende Anforderung ist. Da ich drei Anforderungen auswerten möchte, muss ich einen benutzerdefinierten Handler schreiben, der den AuthorizationHandler für FaceRecognitionRequirement, BodyRecognitionRequirement und VoiceRecognitionRequirement jeweils erweitert. Insbesondere die HandleRequirementAsync-Methode, die ermittelt, ob eine Autorisierungsanforderung erfüllt ist. Diese Methode gibt, da sie asynchron ist, keinen echten Wert zurück, sondern zeigt nur an, dass die Aufgabe abgeschlossen wurde. Die Verarbeitung der Autorisierung besteht darin, eine Anforderung als „erfolgreich“ zu kennzeichnen, indem die Succeed-Methode im Kontext des Autorisierungshandlers aufgerufen wird. Dies wird tatsächlich durch ein „recognizer“-Objekt überprüft, das intern die Cognitive Services-API verwendet (mehr dazu im nächsten Abschnitt). Die Erkennungsaktion, die mit der Recognize-Methode durchgeführt wird, ruft den Namen der identifizierten Person ab und gibt einen Wert (Bewertung) zurück, der das Maß an Vertrauen ausdrückt, dass die Identifizierung mehr (Wert näher an Eins) oder weniger (Wert näher an Null) genau ist. Ein erwarteter Grad wurde im API-Setup angegeben. Sie können diesen Wert für jeden Schwellenwert anpassen, der für Ihre Lösung geeignet ist.

Abbildung 2: Der benutzerdefinierte Autorisierungshandler

public class FaceRequirementHandler :
  AuthorizationHandler<FaceRecognitionRequirement>
{
  protected override Task HandleRequirementAsync(
    AuthorizationHandlerContext context,
      FaceRecognitionRequirement requirement)
  {
    string siteId =
      (context.Resource as HttpContext).Request.Query["siteId"];
    IRecognition recognizer = new FaceRecognition();
    if (recognizer.Recognize(siteId, out string name) >=
      requirement.ConfidenceScore)
    {
      context.User.AddIdentity(new ClaimsIdentity(
        new GenericIdentity(name)));
      context.Succeed(requirement);
    }
    return Task.CompletedTask;
  }
}

Neben der Auswertung der spezifischen Anforderung fügt der Autorisierungshandler dem aktuellen Benutzer auch einen Identitätsanspruch hinzu. Wenn eine Identität erstellt wird, kann ihr mindestens ein Anspruch zugewiesen werden, der von einer vertrauenswürdigen Partei ausgestellt wurde. Ein Anspruch ist ein Name/Wert-Paar, das darstellt, wer die betreffende Person ist. In diesem Fall weise ich den Identitätsanspruch dem Benutzer im Kontext zu. Dieser Anspruch wird dann in der Post-Aktion des Access-Controllers abgerufen und als Teil der Antwort der API zurückgegeben.

Der letzte Schritt zur Aktivierung dieses benutzerdefinierten Autorisierungsprozesses ist die Registrierung des Handlers in der Web-API. Handler werden während der Konfiguration in der services-Sammlung registriert:

services.AddSingleton<IAuthorizationHandler, FaceRequirementHandler>();
services.AddSingleton<IAuthorizationHandler, BodyRequirementHandler>();
services.AddSingleton<IAuthorizationHandler, VoiceRequirementHandler>();

Dieser Code registriert jeden Anforderungshandler als Singleton unter Verwendung des integrierten DI-Frameworks (Dependency Injection) in ASP.NET Core. Eine Instanz des Handlers wird beim Start der Anwendung erstellt, und DI fügt die registrierte Klasse in das relevante Objekt ein.

Gesichtserkennung

Die Lösung verwendet Azure Cognitive Services für die Maschinelles Sehen-API zur Identifizierung des Gesichts und Körpers einer Person. Weitere Informationen zu Cognitive Services und Details zur API finden Sie unter bit.ly/2sxsqry.

Die Maschinelles Sehen-API stellt Gesichtsattributerkennung und Gesichtsüberprüfung bereit. Unter Gesichtserkennung versteht man die Fähigkeit, menschliche Gesichter in einem Bild zu erkennen. Die API gibt die Rechteckkoordinaten der Position des Gesichts innerhalb des verarbeiteten Bilds zurück und kann optional eine Reihe von gesichtsbezogenen Attributen wie Kopfhaltung, Geschlecht, Alter, Emotion, Gesichtsbehaarung und Brille extrahieren. Die Gesichtsüberprüfung hingegen führt eine Authentifizierung eines erkannten Gesichts anhand des zuvor gespeicherten Gesichts einer Person durch. Es wird praktisch ausgewertet, ob zwei Gesichter zur gleichen Person gehören. Dies ist die spezifische API, die ich in diesem Sicherheitsprojekt verwende. Fügen Sie Ihrer Visual Studio-Projektmappe zunächst das folgende NuGet-Paket hinzu: Microsoft.Azure.Cognitive­Services.Vision.Face 2.2.0-preview

Das verwaltete .NET-Paket befindet sich in der Vorschau. Stellen Sie also sicher, dass Sie beim Durchsuchen von NuGet die Option „Include prerelease“ (Vorabversion einbeziehen) aktivieren, wie in Abbildung 3 gezeigt.

NuGet-Paket für die Gesichtserkennungs-API
Abbildung 3: NuGet-Paket für die Gesichtserkennungs-API

Mit dem .NET-Paket ist die Gesichtserkennung und -überprüfung einfach. Im Großen und Ganzen beschreibt die Gesichtserkennung das Vergleichen von zwei verschiedenen Gesichtern, um festzustellen, ob sie ähnlich sind oder zu derselben Person gehören. Die Erkennungsvorgänge verwenden größtenteils die in Abbildung 4 aufgeführten Datenstrukturen.

Abbildung 4: Datenstrukturen für die Gesichtserkennungs-API

Name Beschreibung
DetectedFace Dies ist eine einzelne Gesichtsdarstellung, die von der Gesichtserkennung abgerufen wird. Ihre ID läuft 24 Stunden nach der Erstellung ab.
PersistedFace Wenn DetectedFace-Objekte einer Gruppe (z.B. FaceList oder Person) hinzugefügt werden, werden sie zu PersistedFace-Objekten, die jederzeit abgerufen werden können und nicht ablaufen.
FaceList/LargeFaceList Dies ist eine ausgewählte Liste von PersistedFace-Objekten. Eine FaceList verfügt über eine eindeutige ID, eine Namenszeichenfolge und optional eine Benutzerdaten-Zeichenfolge.
Person Dies ist eine Liste der PersistedFace-Objekte, die zu der gleichen Person gehören. Sie verfügt über eine eindeutige ID, eine Namenszeichenfolge und optional eine Benutzerdaten-Zeichenfolge.
PersonGroup/LargePersonGroup Dies ist eine ausgewählte Liste von Person-Objekten. Sie verfügt über eine eindeutige ID, eine Namenszeichenfolge und optional eine Benutzerdaten-Zeichenfolge. Eine PersonGroup muss trainiert werden, bevor sie in Erkennungsvorgängen verwendet werden kann.

Der Überprüfungsvorgang entnimmt eine Gesichts-ID aus einer Liste der erkannten Gesichter in einem Bild (die DetectedFace-Sammlung) und ermittelt, ob die Gesichter zu derselben Person gehören, indem er die ID mit einer Sammlung von persistent gespeicherten Gesichtern (PersistedFace) vergleicht. Persistent gespeicherte Bilder von Gesichtern weisen eine eindeutige ID und einen Namen auf, die eine Person identifizieren. Eine Gruppe von Personen kann optional in einer PersonGroup erfasst werden, um die Erkennungsleistung zu verbessern. Im Wesentlichen ist eine Person eine grundlegende Identitätseinheit, und für das person-Objekt kann mindestens ein bekanntes Gesicht registriert sein. Jede Person ist innerhalb einer bestimmten PersonGroup (einer Sammlung von Personen) definiert, und die Identifizierung erfolgt anhand einer PersonGroup. Das Sicherheitssystem erstellt mindestens ein -PersonGroup-Objekt und ordnet dieses dann Personen zu. Sobald eine Gruppe erstellt wurde, muss die PersonGroup-Sammlung trainiert werden, bevor eine Identifizierung mit ihr durchgeführt werden kann. Darüber hinaus muss sie nach dem Hinzufügen oder Entfernen einer Person oder nach dem Bearbeiten des registrierten Gesichts einer Person erneut trainiert werden. Das Training erfolgt durch die PersonGroup-Trainings-API. Bei Verwendung der Clientbibliothek ist dies lediglich ein Aufruf der TrainPersonGroupAsync-Methode:

await faceServiceClient.TrainPersonGroupAsync(personGroupId);

Das Training ist ein asynchroner Prozess. Es ist möglich, dass er auch nach der Rückgabe der TrainPersonGroupAsync-Methode noch nicht abgeschlossen ist. Möglicherweise müssen Sie den Trainingsstatus mit der GetPersonGroupTrainingStatusAsync-Methode abfragen, bis er abgeschlossen ist, bevor Sie mit der Gesichtserkennung oder -überprüfung fortfahren können.

Bei der Durchführung der Gesichtsüberprüfung berechnet die Gesichtserkennungs-API die Ähnlichkeit eines erkannten Gesichts unter allen Gesichtern innerhalb einer Gruppe und gibt die am besten vergleichbare(n) Person(en) für dieses Testgesicht zurück. Dies erfolgt über die IdentifyAsync-Methode der Clientbibliothek. Das Testgesicht muss mit den oben genannten Schritten erkannt werden, und die Gesichts-ID wird dann als zweites Argument an die Identifizierungs-API übergeben. Mehrere Gesichts-IDs können gleichzeitig identifiziert werden, und das Ergebnis enthält alle Identifizierungsergebnisse. Standardmäßig gibt Identify nur eine Person zurück, die am besten zu dem Testgesicht passt. Wenn Sie es vorziehen, können Sie den optionalen Parameter maxNumOfCandidatesReturned angeben, damit Identify mehr Kandidaten zurückgibt. Der Code in Abbildung 5 zeigt den Vorgang der Identifizierung und Überprüfung eines Gesichts:

Abbildung 5: Der Gesichtserkennungsvorgang

public class FaceRecognition : IRecognition
{
  public double Recognize(string siteId, out string name)
  {
    FaceClient faceClient = new FaceClient(
      new ApiKeyServiceClientCredentials("<Subscription Key>"))
    {
      Endpoint = "<API Endpoint>"
    };
    ReadImageStream(siteId, out Stream imageStream);
    // Detect faces in the image
    IList<DetectedFace> detectedFaces =
      faceClient.Face.DetectWithStreamAsync(imageStream).Result;
    // Too many faces detected
    if (detectedFaces.Count > 1)
    {
      name = string.Empty;
      return 0;
    }
    IList<Guid> faceIds = detectedFaces.Select(f => f.FaceId.Value).ToList();
    // Identify faces
    IList<IdentifyResult> identifiedFaces =
      faceClient.Face.IdentifyAsync(faceIds, "<Person Group ID>").Result;
    // No faces identified
    if (identifiedFaces.Count == 0)
    {
      name = string.Empty;
      return 0;
    }
    // Get the first candidate (candidates are ranked by confidence)
    IdentifyCandidate candidate =
      identifiedFaces.Single().Candidates.FirstOrDefault();
    // Find the person
    Person person =
      faceClient.PersonGroupPerson.GetAsync("", candidate.PersonId).Result;
    name = person.Name;
    return candidate.Confidence;
  }

Zunächst müssen Sie ein Clientobjekt für die Gesichts-API abrufen, indem Sie Ihren Abonnementschlüssel und den API-Endpunkt übergeben. Sie können beide Werte aus dem Azure Portal abrufen, in dem Sie den Gesichtserkennungs-API-Dienst bereitgestellt haben. Sie erkennen dann jedes Gesicht, das in einem Bild sichtbar ist, das als Datenstrom an die DetectWithStreamAsync-Methode des Face-Objekts des Clients übergeben wird. Das Face-Objekt implementiert die Erkennungs- und Überprüfungsvorgänge für die Gesichtserkennungs-API. Bei den erkannten Gesichtern stelle ich sicher, dass nur eines tatsächlich erkannt wird, und rufe seine ID ab – seine eindeutige Kennung in der registrierten Gesichtssammlung aller autorisierten Personen, die für den Zugang zu diesem Standort autorisiert sind. Die IdentifyAsync-Methode führt dann die Identifizierung des erkannten Gesichts innerhalb einer PersonGroup durch und gibt eine Liste der besten Übereinstimmungen (oder Kandidaten) zurück, sortiert nach Vertrauensstufe. Mit der Personen-ID des ersten Kandidaten rufe ich den Personennamen ab, der schließlich an die Zugangs-Web-API zurückgegeben wird. Die Gesichtserkennungs-Autorisierungsanforderung ist erfüllt.

Spracherkennung

Die Sprechererkennungs-API von Azure Cognitive Services stellt Algorithmen zur Sprecherüberprüfung und Sprecheridentifikation bereit. Stimmen haben einzigartige Eigenschaften, die verwendet werden können, um eine Person zu identifizieren, genau wie ein Fingerabdruck. Die Sicherheitslösung in diesem Artikel verwendet Sprache als Signal für die Zugangskontrolle, wobei die Person eine Passphrase in ein Mikrofon sagt, das als IoT-Gerät registriert ist. Wie bei der Gesichtserkennung erfordert auch die Spracherkennung eine Vorabregistrierung von autorisierten Personen. Die Sprechererkennungs-API bezeichnet eine registrierte Person als ein „Profil“. Bei der Registrierung eines Profils wird die Stimme des Sprechers aufgenommen, die einen bestimmten Satz sagt, dann werden eine Reihe von Merkmalen extrahiert, und der ausgewählte Satz wird erkannt. Zusammen bilden sowohl die extrahierten Merkmale als auch der ausgewählte Satz eine einzigartige Sprachsignatur. Während der Überprüfung werden eine eingegebene Stimme und ein Satz mit der Sprachsignatur und dem Satz der Registrierung verglichen, um zu überprüfen, ob sie von derselben Person stammen und der Satz richtig ist.

Die Codeimplementierung zeigt, dass die Sprechererkennungs-API nicht wie die Gesichtserkennungs-API von einem verwalteten Paket in NuGet profitiert. Daher verfolge ich den Ansatz, die REST-API direkt mit einem HTTP-Clientanforderungs- und -Antwortmechanismus aufzurufen. Der erste Schritt ist die Instanziierung eines HttpClient mit den erforderlichen Parametern für die Authentifizierung und den Datentyp:

public VoiceRecognition()
{
  _httpClient = new HttpClient();
  _httpClient.BaseAddress = new Uri("<API Endpoint>");
  _httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key",
    "<Subscription Key>");
  _httpClient.DefaultRequestHeaders.Accept.Add(
     new MediaTypeWithQualityHeaderValue("application/json"));
}

Die Recognize-Methode in Abbildung 6 entwickelt sich in mehreren Schritten: Nach dem Abrufen des Audiodatenstroms vom IoT-Gerät am Standort wird versucht, diese Audiodaten anhand einer Sammlung von registrierten Profilen zu identifizieren. Die Identifizierung wird in der IdentifyAsync-Methode codiert. Diese asynchrone Methode bereitet eine mehrteilige Anforderungsnachricht vor, die den Audiodatenstrom und die Identifikationsprofil-IDs enthält, und sendet eine POST-Anforderung an einen bestimmten Endpunkt. Wenn die Antwort der API HTTP-Code 202 (Accepted) ist, dann ist der zurückgegebene Wert ein URI des Vorgangs, der im Hintergrund ausgeführt wird. Dieser Vorgang wird am identifizierten URI alle 100 Millisekunden durch die Recognize-Methode auf Vollständigkeit überprüft. Wenn die Methode erfolgreich ist, haben Sie die Profil-ID der identifizierten Person abgerufen. Mit dieser ID können Sie mit der Überprüfung des Audiodatenstroms fortfahren. Dies ist die endgültige Bestätigung, dass die aufgezeichnete Stimme zu der identifizierten Person gehört. Dies wird in der VerifyAsync-Methode implementiert, die ähnlich wie die IdentifyAsync-Methode funktioniert, mit der Ausnahme, dass sie ein VoiceVerificationResponse-Objekt zurückgibt, das das Profil der Person und damit deren Namen enthält. Die Überprüfungsantwort beinhaltet eine Vertrauensstufe, die wie bei der Gesichtserkennungs-API ebenfalls an die Zugangs-Web-API zurückgegeben wird.

Abbildung 6: Spracherkennung

public double Recognize(string siteId, out string name)
{
  ReadAudioStream(siteId, out Stream audioStream);
  Guid[] enrolledProfileIds = GetEnrolledProfilesAsync();
  string operationUri =
    IdentifyAsync(audioStream, enrolledProfileIds).Result;
  IdentificationOperation status = null;
  do
  {
    status = CheckIdentificationStatusAsync(operationUri).Result;
    Thread.Sleep(100);
  } while (status == null);
  Guid profileId = status.ProcessingResult.IdentifiedProfileId;
  VoiceVerificationResponse verification =
    VerifyAsync(profileId, audioStream).Result;
  if (verification == null)
  {
    name = string.Empty;
    return 0;
  }
  Profile profile = GetProfileAsync(profileId).Result;
  name = profile.Name;
  return ToConfidenceScore(verification.Confidence);
}

Ich möchte einige zusätzliche Anmerkungen zu dieser API anbringen, die sich auf die Unterschiede im Vergleich zur Gesichtserkennungs-API beziehen. Die Sprachüberprüfungs-API gibt ein JSON-Objekt zurück, das das Gesamtergebnis des Überprüfungsvorgangs („Accept“ oder „Reject“), die Vertrauensstufe („Low“, „Normal“ oder „High“) und den erkannten Satz enthält:

{
  "result" : "Accept", // [Accept | Reject]
  "confidence" : "Normal", // [Low | Normal | High]
  "phrase": "recognized phrase"
}

Dieses Objekt wird der C#-Klasse VoiceVerificationResponse zugeordnet, um die Verarbeitung innerhalb der VerifyAsync-Methode zu erleichtern, aber seine Vertrauensstufe wird als Text ausgedrückt:

public class VoiceVerificationResponse
{
  [JsonConverter(typeof(StringEnumConverter))]
  public Result Result { get; set; }
  [JsonConverter(typeof(StringEnumConverter))]
  public Confidence Confidence { get; set; }
  public string Phrase { get; set; }
}

Die Zugangs-Web-API hingegen erwartet einen Dezimalwert (Datentyp „double“) zwischen Null und Eins, daher habe ich einige numerische Werte für die Confidence-Enumeration angegeben:

public enum Confidence
{
  Low = 1,
  Normal = 50,
  High = 99
}

Ich habe diese Werte dann in den Datentyp „double“ konvertiert, bevor ich sie an die Zugangs-Web-API zurückgegeben habe:

private double ToConfidenceScore(Confidence confidence)
{
  return (double)confidence / 100.0d;
}

Zusammenfassung

Das war es vorerst für den ersten Teil dieses zweiteiligen Artikels, in dem ich den gesamten Sicherheitsfluss für den Zugang zum Standort behandelt und die Implementierung des Autorisierungsmechanismus in der ASP.NET Core-Web-API anhand benutzerdefinierter Richtlinien und Anforderungen gezeigt habe. Anschließend habe ich die Gesichts- und Spracherkennung unter Verwendung der entsprechenden Cognitive Services-API als Mechanismus zur Zugangsbeschränkung auf der Grundlage biometrischer Informationen von vorab autorisierten oder registrierten Personenprofilen veranschaulicht. Im zweiten Teil dieses Artikels werde ich den Datenstrom von den IoT-Geräten als Auslöser für die Anforderung des Zugangs und die endgültige Bestätigung der Zugangs-API zum Entsperren (oder Verriegeln!) der Zugangstür untersuchen. Ich werde auch einen auf Machine Learning basierenden Anomalieerkennungsdienst behandeln, der bei jedem Zugangsversuch ausgeführt wird, um das Risiko zu identifizieren.

Der Quellcode für diesen ersten Teil der Lösung steht auf GitHub unter bit.ly/2IXPZCo zur Verfügung.


Stefano Tempestaist Microsoft Regional Director, MVP für AI and Business Applications und Mitglied des Blockchain Councils. Tempesta ist regelmäßiger Referent auf internationalen IT-Konferenzen, darunter Microsoft Ignite and Tech Summit, und interessiert sich für blockchain- und KI-bezogene Technologien. Er hat Blogchain Space (blogchain.space) ins Leben gerufen, einen Blog über Blockchaintechnologien, schreibt für MSDN Magazine und MS Dynamics World und veröffentlicht Machine Learning-Experimente im Azure KI-Katalog (gallery.azure.ai).

Unser Dank gilt dem folgenden technischen Experten von Microsoft für die Durchsicht dieses Artikels: Barry Dorrans


Diesen Artikel im MSDN Magazine-Forum diskutieren