using Blazored.LocalStorage;
|
using Microsoft.AspNetCore.Components.Authorization;
|
using System.Security.Claims;
|
using System.Text.Json;
|
|
namespace HotelPms.Client.Blazor.Util
|
{
|
public class ApiAuthenticationStateProvider : AuthenticationStateProvider
|
{
|
public static string? AccessToken { get; set; }
|
|
private readonly ILocalStorageService _localStorage;
|
|
public ApiAuthenticationStateProvider(ILocalStorageService localStorage)
|
{
|
_localStorage = localStorage;
|
}
|
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
{
|
var savedToken = await _localStorage.GetItemAsync<string>("authToken");
|
EnvironmentSetting.Debug($"GetAuthenticationStateAsync:{savedToken}");
|
|
if (string.IsNullOrWhiteSpace(savedToken))
|
{
|
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
}
|
|
if (string.IsNullOrEmpty(AccessToken))
|
{
|
EnvironmentSetting.Debug($"初次认证");
|
//判断savedToken过期?
|
//return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
}
|
|
//_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", savedToken);
|
AccessToken = savedToken;
|
EnvironmentSetting.Debug($"AccessToken:{AccessToken}");
|
|
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(savedToken), "jwt")));
|
}
|
|
public void MarkUserAsAuthenticated(string token)
|
{
|
var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt"));
|
var authState = Task.FromResult(new AuthenticationState(authenticatedUser));
|
NotifyAuthenticationStateChanged(authState);
|
}
|
|
public void MarkUserAsLoggedOut()
|
{
|
var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
|
var authState = Task.FromResult(new AuthenticationState(anonymousUser));
|
NotifyAuthenticationStateChanged(authState);
|
}
|
|
private IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
|
{
|
var claims = new List<Claim>();
|
var payload = jwt.Split('.')[1];
|
var jsonBytes = ParseBase64WithoutPadding(payload);
|
var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);
|
|
keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles);
|
|
if (roles != null)
|
{
|
if (roles.ToString().Trim().StartsWith("["))
|
{
|
var parsedRoles = JsonSerializer.Deserialize<string[]>(roles.ToString());
|
|
foreach (var parsedRole in parsedRoles)
|
{
|
EnvironmentSetting.Debug("parsedRole:" + parsedRole);
|
claims.Add(new Claim(ClaimTypes.Role, parsedRole));
|
}
|
}
|
else
|
{
|
EnvironmentSetting.Debug(roles.ToString());
|
claims.Add(new Claim(ClaimTypes.Role, roles.ToString()));
|
}
|
|
keyValuePairs.Remove(ClaimTypes.Role);
|
}
|
|
claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString())));
|
|
return claims;
|
}
|
|
private byte[] ParseBase64WithoutPadding(string base64)
|
{
|
switch (base64.Length % 4)
|
{
|
case 2: base64 += "=="; break;
|
case 3: base64 += "="; break;
|
}
|
return Convert.FromBase64String(base64);
|
}
|
}
|
}
|