Blazor-Entwicklung: Komponenten, die immer passen
Seite 4: Abstraktion der Authentifizierung
Ein Authentication State Provider ist ein Mechanismus von Blazor. Für einige Blazor-Mechanismen, wie zum Beispiel die Autorisierungsdirektive @attribute [Authorize]
und das rollenabhängige Rendering mit der Komponente <AuthorizeView>
, ist eine von AuthenticationStateProvider abgeleitete Klasse notwendig, die in der Startup-Klasse in der Methode ConfigureServices()
zu registrieren ist:
services.AddScoped<AuthenticationStateProvider, MeinAuthenticationStateProvider>();
In der Implementierung des Authentication State Provider sind zwei Dinge wichtig: Die Klasse muss die Methode async Task<AuthenticationState> GetAuthenticationStateAsync()
überschreiben und in dem zurückgelieferten AuthenticationState die Blazor-Infrastruktur auf deren Anfrage jederzeit über den aktuellen Status (welche Benutzer angemeldet sind oder dass kein Benutzer angemeldet ist) informieren. Zudem muss die Klasse nach der erfolgreichen Benutzeranmeldung beziehungsweise bei einer Benutzerabmeldung die Blazor-Infrastruktur über einen Aufruf von NotifyAuthenticationStateChanged()
unter Angabe eines AuthenticationState-Objekts aktiv benachrichtigen.
In MiracleList wird die eigene Implementierung von Authentication State Provider darüber hinaus ebenfalls für weitere Mechanismen genutzt: An- und Abmeldung von Benutzer und Benutzerinnen, Wechsel des Backends, Prüfung der Verfügbarkeit eines Backends. Dafür gibt es bei MiracleList eine Schnittstelle IMLAuthenticationStateProvider, die zusätzliche Methoden vorsieht; die im folgenden Listing zu sehen sind.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Authorization;
using MiracleList;
namespace MiracleList;
public interface IMLAuthenticationStateProvider
{
/// <summary>
/// Ermittelt den aktuellen Anmeldezustand
/// </summary>
Task<AuthenticationState> GetAuthenticationStateAsync();
/// <summary>
/// Legt das aktuelle Backend fest
/// </summary>
/// <param name="backend">URL oder Connection String</param>
Task SetCurrentBackend(string backend);
/// <summary>
/// Prüft, ob das Backend verfügbar ist
/// </summary>
/// <param name="backend">URL oder Connection String</param>
Task<BackendState> CheckBackend(string backend);
/// <summary>
/// Benutzer anmelden
/// </summary>
Task<LoginInfo> LogIn(string username, string password, string backend);
/// <summary>
/// Benutzer abmelden
/// </summary>
Task Logout();
Listing 4. MiracleList_Interfaces/IMLAuthenticationStateProvider.cs
Von dieser Schnittstelle IMLAuthenticationStateProvider
gibt es dann zwei Implementierungen:
MLAuthenticationStateProvider2Tier
für Blazor Server und Blazor DesktopMLAuthenticationStateProvider3Tier
für Blazor WebAssembly und Blazor MAUI
Beide diese Klassen erben von der in Blazor integrierten Basisklasse AuthenticationStateProvider
und implementieren zusätzlich die eigene Schnittstelle IMLAuthenticationStateProvider
:
public class MLAuthenticationStateProvider3Tier : AuthenticationStateProvider, IMLAuthenticationStateProvider {
…}
Gemeinsame Razor-Komponenten im Projekt
Die Razor Class Library MLBlazorRCL
realisiert alle wesentlichen Razor Components für das MiracleList-Fallbeispiel sodass diese Komponenten in allen Blazor-Varianten einsetzbar (Blazor Server, Blazor WebAssembly. Blazor Desktop und Blazor MAUI) sind. Bild 6 zeigt, wie der Hauptbildschirm von MiracleList in verschiedene Komponenten aufgeteilt ist.
Gemeinsame Blazor-Komponenten für alle Ansichten:
MainLayout.razor
ist die Masterpage, die die obere weiße Leiste mit Logo (links) und Hamburger-Menü (rechts) darstellt. Sofern ein Benutzer angemeldet und der Bildschirm groß genug ist, zeigt die weiße Leiste in der Mitte auch Statusinformationen.ConnectionState.razor
: Komponente, die im Kopfbereich der Anwendung den Verbindungstatus darstellt
Gemeinsame Blazor-Komponenten für die Anmeldeansicht:
Login.razor
: Anmeldeformular, das bei erfolgreicher Anmeldung auf /main weiterleitetServerState.razor
: Ein Teil des Anmeldeformulars, der die Erreichbarkeit in der appsettings.json erfassten Backend-Systeme anzeigt.
Gemeinsame Blazor-Komponenten für die Hauptansicht:
Main.razor
: Hauptansicht /main beinhaltetAufgabenkategorieliste und Aufgabenliste mit Anlegen und Löschen von Kategorien und Aufgaben sowie Drag&Drop von Aufgaben auf KategorienTaskElement.razor
: Darstellung einer einzelnen Aufgabe innerhalb der Komponente Main.razorTaskEdit.razor[code]: Bearbeitungsformular für eine Aufgabe mit Validierung der Eingaben
- [code]SubTaskList.razor: Liste der Unteraufgaben einer Aufgabe mit Anlegen und Löschen von Unteraufgaben
TaskGrid.razor
: Bearbeitung der Aufgaben in einem Datagrid (von Radzen, kostenfrei).
Außerdem beinhaltet die [code]MLBlazorRCL[/CODE] gemeinsame Grafiken und Styles (.css), wie sie in Bild 7 zu sehen sind:
Fazit
Der Beitrag "Eine Blazor-App für alle Plattformen“ hat gezeigt, wie Entwickler und Entwicklerinnen grundsätzlich gemeinsame Razor Components und statische Webartefakte in mehreren Blazor-Anwendungen nutzen können, auch wenn diese auf verschiedenen Blazor-Arten basieren. In diesem Artikel ging es dann um die Abstraktion von Daten- und Ressourcenzugriffen von der Schichtenarchitektur. Mit dem hier gezeigten Weg ist es – mit viel Codegenerierung – auf effiziente Weise möglich, Razor Components zu schreiben, die wahlweise Daten sowohl direkt von einem Datenbankmanagementsystem (2-Tier-Architektur) als auch via Webservice (3-Tier-Architektur).
Dr. Holger Schwichtenberg
ist Chief Technology Expert bei MAXIMAGO, die Innovations- und Experience-getriebener Softwareentwicklung, unter anderem in hochkritischen sicherheitstechnischen Bereichen, anbietet. Zudem ist er Leiter des Expertennetzwerks www.IT-Visions.de, das mit 43 Experten zahlreiche mittlere und große Unternehmen durch Beratung und Schulung bei der Entwicklung sowie dem Betrieb von Software unterstützt.
(fms)