Files
Atomx/Atomx.Admin/Atomx.Admin.Client/Utils/PersistentAuthenticationStateProvider.cs
2025-12-04 03:08:29 +08:00

141 lines
5.9 KiB
C#

using Blazored.LocalStorage;
using Atomx.Common.Configuration;
using Atomx.Utils.Extension;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Atomx.Common.Constants;
namespace Atomx.Admin.Client.Utils
{
public class PersistentAuthenticationStateProvider : AuthenticationStateProvider
{
readonly ClaimsPrincipal anonymous = new(new ClaimsIdentity());
static readonly Task<AuthenticationState> defaultUnauthenticatedTask = Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())));
readonly Task<AuthenticationState> authenticationStateTask = defaultUnauthenticatedTask;
readonly ILocalStorageService _localStorage;
public PersistentAuthenticationStateProvider(PersistentComponentState state, ILocalStorageService localStorageService)
{
_localStorage = localStorageService;
if (!state.TryTakeFromJson<UserInfo>(nameof(UserInfo), out var userInfo) || userInfo is null)
{
return;
}
var claims = new List<Claim>
{
new(ClaimKeys.Id, userInfo.Id.ToString()),
new(ClaimKeys.Name, userInfo.Name),
new(ClaimKeys.Email, userInfo.Email),
new(ClaimKeys.Mobile, userInfo.MobilePhone),
new(ClaimKeys.Role, userInfo.Role),
};
foreach (var role in userInfo.Permissions)
{
claims.Add(new Claim(ClaimKeys.Permission, role));
}
authenticationStateTask = Task.FromResult(
new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType: nameof(PersistentAuthenticationStateProvider)))));
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
try
{
var jwtToken = await _localStorage.GetItemAsStringAsync(StorageKeys.AccessToken);
if (string.IsNullOrEmpty(jwtToken))
return await Task.FromResult(new AuthenticationState(anonymous));
else
{
var getUserClaims = DecryptToken(jwtToken);
if (getUserClaims == null)
return await Task.FromResult(new AuthenticationState(anonymous));
else
{
var claimsPrincipal = SetClaimPrincipal(getUserClaims);
return await Task.FromResult(new AuthenticationState(claimsPrincipal));
}
}
}
catch
{
return await Task.FromResult(new AuthenticationState(anonymous));
}
}
public ClaimsPrincipal SetClaimPrincipal(UserInfo customUserClaims)
{
if (string.IsNullOrEmpty(customUserClaims.Name))
return new ClaimsPrincipal();
else
{
var claims = new List<Claim>
{
new(ClaimKeys.Id, customUserClaims.Id.ToString()),
new(ClaimKeys.Name, customUserClaims.Name),
new(ClaimKeys.Email, customUserClaims.Email),
new(ClaimKeys.Mobile, customUserClaims.MobilePhone),
new(ClaimKeys.Role, customUserClaims.Role.ToString()),
};
foreach (var role in customUserClaims.Permissions)
{
claims.Add(new Claim(ClaimKeys.Permission, role));
}
return new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType: nameof(PersistentAuthenticationStateProvider)));
}
}
public void UpdateAuthenticationState(string jwtToken = "")
{
var claimsPrincipal = new ClaimsPrincipal();
if (!string.IsNullOrEmpty(jwtToken))
{
var getUserClaims = DecryptToken(jwtToken);
claimsPrincipal = SetClaimPrincipal(getUserClaims);
}
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(claimsPrincipal)));
}
private UserInfo DecryptToken(string jwtToken)
{
if (string.IsNullOrEmpty(jwtToken))
return new UserInfo();
else
{
var handler = new JwtSecurityTokenHandler();
var token = handler.ReadJwtToken(jwtToken);
var id = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Id)?.Value ?? string.Empty;
var name = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Name)?.Value ?? string.Empty;
var email = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Email)?.Value ?? string.Empty;
var phone = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Mobile)?.Value ?? string.Empty;
var role = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Role)?.Value ?? string.Empty;
var permissions = token.Claims.Where(x => x.Type == ClaimKeys.Permission).Select(s => s.Value).ToArray();
return new UserInfo(id.ToLong(), name, email, phone, role, permissions);
}
}
public async Task MarkUserAsLoggedOut()
{
await _localStorage.RemoveItemAsync(StorageKeys.AccessToken);
await _localStorage.RemoveItemAsync(StorageKeys.RefreshToken);
var authState = Task.FromResult(new AuthenticationState(anonymous));
NotifyAuthenticationStateChanged(authState);
}
}
public record UserInfo(long Id = 0, string Name = null!, string Email = null!, string MobilePhone = null!, string Role = null!, string[] Permissions = null!);
}