CustomAuthStateProvider in .NET 9, MudBlazorC#

Ein Treffpunkt für C#-Programmierer
Anonymous
 CustomAuthStateProvider in .NET 9, MudBlazor

Post by Anonymous »

Ich versuche, einen CustomAuthStateProvider zu implementieren. Ziel ist es, dass der jeweilige Benutzer in der gesamten Anwendung angemeldet ist und ich auf allen Seiten den Namen, die ID (Guid) und den Rang beim Anbieter abrufen kann.
Ein erneutes Laden der Seite lässt sich nicht vermeiden. Dies muss auch gewährleistet sein, daher das Cookie.
Ich habe hier bereits nach einem CustomAuthStateProvider gefragt, aber leider will das JavaScript nicht in der aktuellen Anwendung laden. Es befindet sich in App.razor. Können Sie bitte überprüfen, was falsch ist?
In App.razor:

Code: Select all

function WriteCookie(name, value, days) {
var expires;
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.ToGmtString();
}
else {
expires = "";
}
document.cookie = name + "=" + value + expires + "; path=/";
}

function ReadCookie(name) {
const value = `; ${document.Cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length == 2) return parts.pop().split(';').shift();
}

In LoginDialog.razor:

Code: Select all

internal async Task PerformLogin()
{
Data.User.User? loggedInUser = await Data.User.Loader.ReadUsersForLogin(_username, _password);

if (loggedInUser != null)
{
AuthenticationState authenticationState = await ((CustomAuthStateProvider)AuthStateProvider).ChangeUser(loggedInUser.UserName, loggedInUser.Id, loggedInUser.Rank.ToString());

MudDialog?.Close(DialogResult.Ok(true));
}
}

Code: Select all

MainLayout.razor
:

Code: Select all

private async void ShowLoginDialog(MouseEventArgs args)
{
var parameters = new DialogParameters { { "IsDarkMode", this._isDarkMode } };
MudBlazor.IDialogReference? dialog = await DialogService.ShowAsync("Login", parameters);

DialogResult? result = await dialog.Result;

if (result != null && !result.Canceled)
{
StateHasChanged();
Navigation.NavigateTo(Navigation.Uri, forceLoad: true);
}

_authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
_user = _authState.User;

if (_user.Identity != null && _user.Identity.IsAuthenticated)
{
var roleClaim = _user.FindFirst(System.Security.Claims.ClaimTypes.Role);

if (roleClaim != null)
{
_rank = (Data.User.User.Ranks)Enum.Parse(typeof(Data.User.User.Ranks), roleClaim.Value);
}
}
}

Code: Select all

CustomAuthStateProvider.cs
:

Code: Select all

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.IdentityModel.Tokens;
using Microsoft.JSInterop;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

public class CustomAuthStateProvider : AuthenticationStateProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IJSRuntime _js;

public CustomAuthStateProvider(IHttpContextAccessor httpContextAccessor, IJSRuntime js)
{
this._httpContextAccessor = httpContextAccessor;
this._js = js;
}

public override async Task GetAuthenticationStateAsync()
{
string usertoken = "";
if (_httpContextAccessor.HttpContext != null)
{
if (!_httpContextAccessor.HttpContext.Response.HasStarted)
{

usertoken = _httpContextAccessor.HttpContext.Request.Cookies["usertoken"];
}
else
{
usertoken = await _js.InvokeAsync("ReadCookie", "usertoken");
}
}
else
{
usertoken = await _js.InvokeAsync("ReadCookie", "usertoken");
}

if (string.IsNullOrEmpty(usertoken))
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
var tokenHandler = new JwtSecurityTokenHandler();
var identity = new ClaimsIdentity(tokenHandler.ReadJwtToken(usertoken).Claims, CookieAuthenticationDefaults.AuthenticationScheme);
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(identity)));
}

public async Task  ChangeUser(string username, Guid guidId, string rank)
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Sid, guidId.ToString()),
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Role, rank)
}, CookieAuthenticationDefaults.AuthenticationScheme);

var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = identity,
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = null // No signing key
};

var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
var usertoken = tokenHandler.WriteToken(token);

//when Anonymous set empty cookie
if (username == "Anonymous")
{
usertoken = "";
}

if (_httpContextAccessor.HttpContext != null)
{
if (!_httpContextAccessor.HttpContext.Response.HasStarted)
{

_httpContextAccessor.HttpContext.Response.Cookies.Append("usertoken", usertoken);
}
else
{
await _js.InvokeVoidAsync("WriteCookie", "usertoken", usertoken, DateTime.Now.AddMinutes(1));
}
}
else
{
await _js.InvokeVoidAsync("WriteCookie", "usertoken", usertoken, DateTime.Now.AddMinutes(1));

}
var authState = await this.GetAuthenticationStateAsync();
this.NotifyAuthenticationStateChanged(Task.FromResult(authState));
return authState;
}

public async Task Logout()
{
await ChangeUser("Anonymous", Guid.Empty, "Anonymous");
var authState = await this.GetAuthenticationStateAsync();
this.NotifyAuthenticationStateChanged(Task.FromResult(authState));
return authState;
}
}
In Program.cs:

Code: Select all

builder.Services.AddScoped();
builder.Services.AddHttpContextAccessor();
builder.Services.AddCascadingAuthenticationState();
Bearbeiten:

Das JavaScript wird jetzt geladen, weil ich den Code in App.razor wie folgt geändert habe.

Code: Select all





function WriteCookie(name, value, days) {
var expires;
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
}
else {
expires = "";
}
document.cookie = name + "=" + value + expires + "; path=/";
}

function ReadCookie(name) {
console.log("test");
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}


Leider bleibt die Anmeldung nach dem Klicken auf OK im Anmeldedialog nicht aktiv, obwohl ein positives Ergebnis zurückgegeben wird.
Das Feld AuthenticationState? _authState ist null, wenn die Seite aktualisiert wird.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post