chore
This commit is contained in:
@@ -19,9 +19,6 @@ builder.Services.AddScoped<IPermissionService, ClientPermissionService>();
|
||||
builder.Services.AddScoped<IconsExtension>();
|
||||
builder.Services.AddScoped<ILocalizationService, LocalizationClientService>();
|
||||
|
||||
// Token provider<65><72>WASM<53><4D>: <20><> localStorage <20><>ȡ access token
|
||||
builder.Services.AddScoped<ITokenProvider, ClientTokenProvider>();
|
||||
|
||||
// ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD> token & ˢ<>µ<EFBFBD> DelegatingHandler
|
||||
builder.Services.AddScoped<AuthHeaderHandler>();
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Atomx.Admin.Client.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// 统一的 Token 提供器接口(放在共享项目)
|
||||
/// 目标:
|
||||
/// - Server 与 WASM 使用相同的接口类型以避免 DI 注入类型不一致
|
||||
/// - 仅负责“提供”当前可用的 access token(不承担刷新策略)
|
||||
/// </summary>
|
||||
public interface ITokenProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回当前可用的 access token(如果没有则返回 null)
|
||||
/// </summary>
|
||||
Task<string?> GetTokenAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 快速判断当前 token 是否存在且(如果可以解析为 JWT)未过期。
|
||||
/// 注意:此方法为快速检查,不能替代服务端的完整验证。
|
||||
/// </summary>
|
||||
Task<bool> IsTokenValidAsync();
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ namespace Atomx.Admin.Client.Utils
|
||||
/// </summary>
|
||||
public class AuthHeaderHandler : DelegatingHandler
|
||||
{
|
||||
private readonly ITokenProvider _tokenProvider;
|
||||
private readonly NavigationManager _navigationManager;
|
||||
private readonly ILogger<AuthHeaderHandler> _logger;
|
||||
private readonly ILocalStorageService _localStorage;
|
||||
@@ -26,13 +25,11 @@ namespace Atomx.Admin.Client.Utils
|
||||
private static readonly SemaphoreSlim _refreshLock = new(1, 1);
|
||||
|
||||
public AuthHeaderHandler(
|
||||
ITokenProvider tokenProvider,
|
||||
NavigationManager navigationManager,
|
||||
ILogger<AuthHeaderHandler> logger,
|
||||
ILocalStorageService localStorage,
|
||||
IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_tokenProvider = tokenProvider;
|
||||
_navigationManager = navigationManager;
|
||||
_logger = logger;
|
||||
_localStorage = localStorage;
|
||||
@@ -45,7 +42,12 @@ namespace Atomx.Admin.Client.Utils
|
||||
try
|
||||
{
|
||||
// 从 ITokenProvider 获取当前 access token(WASM: ClientTokenProvider 从 localStorage 读取)
|
||||
var token = await _tokenProvider.GetTokenAsync();
|
||||
var token = string.Empty;
|
||||
try
|
||||
{
|
||||
token = await _localStorage.GetItemAsync<string>(StorageKeys.AccessToken);
|
||||
}
|
||||
catch { }
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
@@ -206,5 +208,20 @@ namespace Atomx.Admin.Client.Utils
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
private async Task HandleUnauthorizedAsync()
|
||||
{
|
||||
// 在WASM模式下重定向到登录页
|
||||
if (OperatingSystem.IsBrowser())
|
||||
{
|
||||
_navigationManager.NavigateTo("/account/login", true);
|
||||
}
|
||||
// 在Server模式下可以执行其他操作
|
||||
else
|
||||
{
|
||||
// Server端的处理逻辑
|
||||
_logger.LogWarning("Unauthorized access detected in server mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using Atomx.Admin.Client.Services;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Atomx.Admin.Client.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// WASM 客户端下的 Token 提供器(实现共享的 ITokenProvider)
|
||||
/// - 直接从浏览器 storage(localStorage/sessionStorage)读取 access token
|
||||
/// - 设计为轻量,仅负责读取 token;刷新逻辑放在 AuthHeaderHandler / 后端 Refresh 接口
|
||||
/// </summary>
|
||||
public class ClientTokenProvider : ITokenProvider
|
||||
{
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
|
||||
public ClientTokenProvider(IJSRuntime jsRuntime)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
public async Task<string?> GetTokenAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _jsRuntime.InvokeAsync<string>("localStorage.getItem", "accessToken");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> IsTokenValidAsync()
|
||||
{
|
||||
var token = await GetTokenAsync();
|
||||
return !string.IsNullOrEmpty(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user