84 lines
3.2 KiB
Plaintext
84 lines
3.2 KiB
Plaintext
@page "/logout"
|
||
@layout EmptyLayout
|
||
@inject IJSRuntime JS
|
||
@inject ILogger<Logout> Logger
|
||
@inject NavigationManager Navigation
|
||
@inject AuthenticationStateProvider AuthStateProvider
|
||
@inject HttpService HttpService
|
||
@using System.Text.Json
|
||
|
||
@code {
|
||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||
{
|
||
if (!firstRender) return;
|
||
|
||
try
|
||
{
|
||
// 如果运行在浏览器 (WASM),直接调用后端 API 并清除 localStorage / provider
|
||
if (OperatingSystem.IsBrowser())
|
||
{
|
||
Logger.LogInformation("WASM logout: call API and clear local storage");
|
||
try
|
||
{
|
||
await HttpService.Post<ApiResult<string>>("/api/sign/out", null);
|
||
}
|
||
catch { /* 忽略网络错误,仍继续清理客户端状态 */ }
|
||
|
||
if (AuthStateProvider is PersistentAuthenticationStateProvider provider)
|
||
{
|
||
await provider.MarkUserAsLoggedOut();
|
||
}
|
||
|
||
Navigation.NavigateTo("/account/login");
|
||
}
|
||
else
|
||
{
|
||
// Server 模式:通过浏览器 fetch 发起带凭据的请求以便浏览器接收并删除 Cookie,然后强制重载
|
||
Logger.LogInformation("Server logout: use browser fetch to call /api/sign/out");
|
||
var jsResult = await JS.InvokeAsync<JsonElement>("__atomx_post_json", "/api/sign/out", (object?)null);
|
||
|
||
// 尝试解析返回,忽略细节
|
||
var success = jsResult.ValueKind == JsonValueKind.Object && jsResult.TryGetProperty("success", out var sp) && sp.GetBoolean();
|
||
Logger.LogInformation("Server logout result: {Success}", success);
|
||
|
||
try
|
||
{
|
||
// 清理 localStorage(如果有的话)
|
||
await localStorage.RemoveItemAsync(StorageKeys.AccessToken);
|
||
await localStorage.RemoveItemAsync(StorageKeys.RefreshToken);
|
||
}
|
||
catch { }
|
||
|
||
// 尽管我们可能已经处理了服务器态,强制重新加载确保 Circuit 更新
|
||
Navigation.NavigateTo("/account/login", forceLoad: true);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Logger.LogWarning(ex, "Logout failed but proceeding to login page");
|
||
Navigation.NavigateTo("/account/login", forceLoad: true);
|
||
}
|
||
}
|
||
}
|
||
|
||
@* 页面内 JS 辅助:用于在 Server 模式下从浏览器发起 POST 并携带凭证,使浏览器接收 Set-Cookie/删除 Cookie *@
|
||
<script>
|
||
window.__atomx_post_json = async function (url, data) {
|
||
try {
|
||
const res = await fetch(url, {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
credentials: 'include',
|
||
body: data ? JSON.stringify(data) : null
|
||
});
|
||
const text = await res.text();
|
||
try {
|
||
return JSON.parse(text);
|
||
} catch {
|
||
return { success: res.ok, message: text };
|
||
}
|
||
} catch (err) {
|
||
return { success: false, message: err?.toString() ?? 'network error' };
|
||
}
|
||
};
|
||
</script> |