SignalR mit Authentifizierung in Angular verwenden

SignalR mit Authentifizierung in Angular verwenden

15. Nov. 2024 | Gregor Koletzki | 1 Min. Lesezeit

SignalR ist eine Bibliothek von Microsoft, die es ermöglicht, in Echtzeit Daten zwischen einem Server und Clients auszutauschen. Wenn man SignalR in einer Angular-Anwendung verwendet, kann es notwendig sein, Authentifizierungsmechanismen zu implementieren, um sicherzustellen, dass nur autorisierte Benutzer Zugriff auf die SignalR-Verbindungen haben. In diesem Artikel zeige ich, wie man SignalR in Angular mit JWT-Token-Authentifizierung integriert.

Voraussetzungen

  • Angular (Version 15 oder höher)
  • ASP.NET Core (für die Backend-API)
  • Node.js und npm (für Angular CLI)
  • Kenntnisse in Angular, TypeScript, C#, und ASP.NET Core

1. Backend-Setup (ASP.NET Core)

Zuerst richten wir das Backend mit ASP.NET Core ein. Es ist wichtig, die Authentifizierung mit JWT-Token zu konfigurieren, da Angular diese Tokens für die Verbindung zu SignalR verwenden wird.

1.1. SignalR Hub erstellen

Erstellen Sie eine neue Hub-Klasse, z.B. ChatHub.cs.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;

[Authorize] // Autorisiert nur authentifizierte Benutzer
public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

1.2. JWT-Authentifizierung konfigurieren

In der Program.cs (oder Startup.cs für ältere Versionen) konfigurieren wir die JWT-Authentifizierung.

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// JWT-Authentifizierung konfigurieren
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = "yourissuer",
        ValidAudience = "youraudience",
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("yoursecretkey"))
    };

    // SignalR spezifische Konfiguration
    options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            // Token aus der Abfragezeichenfolge extrahieren
            var accessToken = context.Request.Query["access_token"];

            // Überprüfen, ob der Hub-Aufruf gemacht wird
            var path = context.HttpContext.Request.Path;
            if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/chathub"))
            {
                context.Token = accessToken;
            }

            return Task.CompletedTask;
        }
    };
});

app.UseAuthentication();
app.UseAuthorization();

app.MapHub<ChatHub>("/chathub");

app.Run();

1.3. Angular-Client vorbereiten

Installieren Sie die notwendigen Pakete:

npm install @microsoft/signalr

2. Angular Client-Setup

Nun richten wir den Angular-Client ein.

2.1. SignalR-Service erstellen

Erstellen Sie einen neuen Service signalr.service.ts.

import { Injectable } from '@angular/core';
import * as signalR from '@microsoft/signalr';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class SignalRService {
  private hubConnection: signalR.HubConnection;
  public messageReceived = new BehaviorSubject<{ user: string, message: string } | null>(null);

  constructor(private http: HttpClient) {}

  public startConnection(token: string): void {
    this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl('https://localhost:5001/chathub', {
        accessTokenFactory: () => token,
      })
      .withAutomaticReconnect()
      .build();

    this.hubConnection
      .start()
      .then(() => console.log('SignalR-Verbindung gestartet'))
      .catch((err) => console.error('Fehler beim Starten der SignalR-Verbindung:', err));

    this.hubConnection.on('ReceiveMessage', (user: string, message: string) => {
      this.messageReceived.next({ user, message });
    });
  }

  public sendMessage(user: string, message: string): void {
    this.hubConnection
      .invoke('SendMessage', user, message)
      .catch((err) => console.error('Fehler beim Senden der Nachricht:', err));
  }
}

2.2. Nutzung des Services in einer Komponente

Erstellen Sie eine Komponente chat.component.ts.

import { Component, OnInit } from '@angular/core';
import { SignalRService } from './signalr.service';
import { AuthService } from './auth.service';

@Component({
  selector: 'app-chat',
  template: `
    <div>
      <h2>Chat</h2>
      <div *ngFor="let msg of messages">
        <strong>{{ msg.user }}:</strong> {{ msg.message }}
      </div>
      <input [(ngModel)]="user" placeholder="Benutzername" />
      <input [(ngModel)]="message" placeholder="Nachricht" />
      <button (click)="sendMessage()">Senden</button>
    </div>
  `,
})
export class ChatComponent implements OnInit {
  user = '';
  message = '';
  messages: { user: string; message: string }[] = [];

  constructor(
    private signalRService: SignalRService,
    private authService: AuthService
  ) {}

  ngOnInit(): void {
    const token = this.authService.getToken(); // Token vom AuthService holen
    this.signalRService.startConnection(token);

    this.signalRService.messageReceived.subscribe((msg) => {
      if (msg) this.messages.push(msg);
    });
  }

  sendMessage(): void {
    this.signalRService.sendMessage(this.user, this.message);
    this.message = '';
  }
}

2.3. AuthService zur Verwaltung des Tokens

Erstellen Sie den auth.service.ts, um den JWT-Token zu handhaben.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class AuthService {
  private tokenKey = 'authToken';

  constructor() {}

  setToken(token: string): void {
    localStorage.setItem(this.tokenKey, token);
  }

  getToken(): string {
    return localStorage.getItem(this.tokenKey) ?? '';
  }
}

3. Fazit

Mit dieser Implementierung haben wir eine einfache Möglichkeit geschaffen, SignalR in einer Angular-Anwendung mit JWT-Authentifizierung zu verwenden. Dabei sind die Hauptpunkte:

  • Authentifizierung: Sicherstellen, dass nur autorisierte Benutzer mit dem SignalR-Hub kommunizieren können.
  • JWT-Token: Das Token wird in der access_token-Abfragezeichenfolge übergeben und vom Server validiert.
  • Echtzeit-Kommunikation: Der Angular-Client empfängt Nachrichten in Echtzeit und zeigt sie an. Mit dieser Methode kann SignalR sicher in Angular-Anwendungen integriert werden, um eine Authentifizierung und Autorisierung durchzuführen.

Weiterführende Artikel

Kategorien

Kontaktieren Sie uns:

Harksheider Weg 60H,
25451 Quickborn
+49 1520 40 73 253
info@gk-itsolutions.de

Schnellzugriff:

Folgt uns auf: