在刷新页面之前,Blazor Web Assembly (wasm) 不会使客户端 cookie 过期

Posted

技术标签:

【中文标题】在刷新页面之前,Blazor Web Assembly (wasm) 不会使客户端 cookie 过期【英文标题】:Blazor Web Assembly (wasm) won't expire client side cookie until page is refreshed 【发布时间】:2021-08-09 05:55:00 【问题描述】:

我正在使用 Visual Studio 2019 中可用的最新 .NET 5 Blazor Web Assembly Core Hosted 模板。它已经支持开箱即用的身份验证。

问题是我可以像这样在 Startup.cs 中的 ConfigureServices(IServiceCollection services) 方法中使 .NET 托管(服务器)端的 Cookie 过期:

  services.ConfigureApplicationCookie(options => 
        
            options.AccessDeniedPath = "/Identity/Account/AccessDenied";
            options.Cookie.Name = "MyCookie";
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
            options.LoginPath = "/Identity/Account/Login";
            options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
            options.SlidingExpiration = true;     
        );

但是,我的要求是,当会话在 20 分钟后到期时,应要求用户再次登录。我的问题是cookie仅在浏览器关闭或用户点击重新加载时才会过期。与此同时,我可以点击所有控制器,即使它们中有 [Authorize] 标签。理想的情况是当用户调用控制器然后它重定向到登录。

登录后会创建 Cookie。

当时间过去了,cookies 消失了,但用户仍然拥有所有权限。

【问题讨论】:

问题在于身份验证状态从未更新,因为 cookie 已过期,您的用户不再经过身份验证。该解决方案需要您的一些投资和知识。一般来说,您应该实现 Authentication State 提供程序,其中您应该有代码(循环)来检查 cookie 是否会在 20 分钟后过期,如果是,您可以警告您的用户这一事实,也许要求他注销再登录等。你这里可能还有代码来验证其他因素.... 在使用 IdentityServer 继续您的项目之前,请确保您已阅读 Microsoft 的这篇文章 (devblogs.microsoft.com/aspnet/…) 及其随附的 cmets。就我个人而言,我已经完成了 IdentityServer。 @enet 你有例子吗?我似乎在网上找不到任何东西。 不,抱歉,我不知道 Internet 上有任何代码示例这样做...但是,您应该首先检查 RevalidatingServerAuthenticationStateProvider 类及其派生类(注意:它是 Blazor 服务器,不是 WebAssembly,但它应该让您了解应该如何实现身份验证状态提供程序)。您需要覆盖某个可以访问您的 cookie 过期时间的方法,例如数据......并且您需要从该方法触发 MainLayout 组件可能订阅的事件以通知 cookie已经过期了,要去..etc 【参考方案1】:

使用以下函数将 Utilities.js javascript 文件添加到客户端项目中的 wwwroot/js。

function initializeInactivityTimer(dotnetHelper) 
var timer;
document.onmousemove = resetTimer;
document.onkeypress = resetTimer;

function resetTimer() 
    clearTimeout(timer);
    timer = setTimeout(logout, 1200000);


function logout() 
    dotnetHelper.invokeMethodAsync("Logout");

确保将其添加到 wwwroot/index.html 的末尾

 <script src="js/Utilities.js"></script>

在MainLayout.razor的Server项目中添加如下方法

[JSInvokable]
public async Task Logout()

    var authState = await AuthenticationState;
    if (authState.User.Identity.IsAuthenticated)
    
        await SignOutManager.SetSignOutState();

        NavigationManager.NavigateTo("authentication/logout");
    

确保将 MainLayout.razor 添加到顶部

@inject NavigationManager NavigationManager
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject IJSRuntime js
@inject SignOutSessionStateManager SignOutManager

同时添加这个级联参数

[CascadingParameter]
public Task<AuthenticationState> AuthenticationState  get; set; 

仍然在 MainLayout.razor 上的 Task OnInitializedAsync() 上,像这样调用 javascript 函数:

await js.InvokeVoidAsync("initializeInactivityTimer",  DotNetObjectReference.Create(this));

保留 StartUp.cs 上的所有修改。它们适用于用户重新加载或关闭浏览器时。如果没有鼠标移动或按键,这个js函数将注销用户。

参考

https://www.youtube.com/watch?v=cOV0uV_E6bU

https://github.com/gavilanch/BlazorMovies/tree/master/ASP.NET%20Core%205/Module%207%20-%20Security

【讨论】:

以上是关于在刷新页面之前,Blazor Web Assembly (wasm) 不会使客户端 cookie 过期的主要内容,如果未能解决你的问题,请参考以下文章

在 Blazor 中自动刷新组件

服务器端 Blazor:刷新页面后如何保持用户身份验证?

Blazor-断开连接后重新加载浏览器

我们可以在常规的非 Blazor HTML 页面中将 Blazor 组件用作 Web 组件吗?

Blazor - 在 API 调用时显示等待或微调器

为啥.cshtml更改后刷新页面不更新