简体   繁体   English

如何从 Blazor 服务器端应用程序成功注销?

[英]How to sign out successfully from a Blazor server-side app?

I'm logging out by doing the following:我通过执行以下操作注销:

public class LogoutModel : PageModel
{
    public async Task OnGet(string redirectUri)
    {
        await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties
        {
            RedirectUri = redirectUri,
        });
    }
}

signing out should be working because I get redirected to the correct page in which I have a link to go back to the home page:注销应该可以正常工作,因为我被重定向到正确的页面,在该页面中我有一个指向 go 的链接回到主页:

<p class="mb-1">
    @{
        var url = $"{navigationManager.BaseUri}";

        <NavLink class="nav-link" href=@($"{url}") Match="NavLinkMatch.Prefix">
            Login again
        </NavLink>
    }
</p> 

The razor page is as follows: razor页面如下:

<AuthorizeView>
    <Authorized>
        @{
            navigationManager.NavigateTo("Main", forceLoad: true);
        }
    </Authorized>
    <NotAuthorized>
        @{
            var returnUrl = $"{navigationManager.BaseUri}{options.LoginCallbackUrl}";
            navigationManager.NavigateTo($"Login?redirectUri={returnUrl}", forceLoad: true);
        }
    </NotAuthorized>
 </AuthorizeView>

At this stage, the code within the Authorized tag gets executed and I get redirected immediately to the main page.在此阶段, Authorized标签内的代码被执行,我立即被重定向到主页。 Which should not happen.这不应该发生。

The OpenId settings in Startup.cs are: Startup.cs中的 OpenId 设置为:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})

Why is the app still thinking that the user is still authorized?为什么应用程序仍然认为用户仍然被授权? Am I missing a step?我错过了一步吗?

You have to get authentication state on main layout - lifecycle event OnInitialized{Async}.您必须在主布局上获得身份验证 state - 生命周期事件 OnInitialized{Async}。

protected override async Task OnInitializedAsync()
{
    var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
    User = authState.User;
    if (!User.Identity.IsAuthenticated)
    {
        NavMan.NavigateTo("Identity/Account/Login", true);
    }
}

Keep in mind Blazor server side is SPA application, this mean the page is never reload, DOM is update with the server <-> SignalR <-> Javascript tunnel.请记住 Blazor 服务器端是 SPA 应用程序,这意味着页面永远不会重新加载,DOM 会随着服务器 <-> SignalR <-> Javascript 隧道进行更新。 This mean cookie authentication is only possible is you force page reload.这意味着 cookie 身份验证只有在您强制重新加载页面时才有可能。

To understand how to handle authentication, including sign out, have a look at this example.要了解如何处理身份验证(包括注销),请查看此示例。 https://github.com/iso8859/AspNetCoreAuthMultiLang https://github.com/iso8859/AspNetCoreAuthMultiLang

In AuthenticationStateProvider.GetAuthenticationStateAsync implementation you must return empty token在 AuthenticationStateProvider.GetAuthenticationStateAsync 实现中,您必须返回空令牌

new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));新的 AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); = not authenticated. = 未验证。

There is no need to subclass any classes.无需子类化任何类。 The way to solve the problem is by first doing:解决问题的方法是首先执行:

public class LogoutModel : PageModel
{
    public async Task OnGet(string redirectUri)
    {
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties
        {
            RedirectUri = redirectUri,
        });
    }
}

This will sign out the user from cookies and OpenId.这将从 cookies 和 OpenId 中注销用户。 To navigate here, one can do the following in a razor component:要在此处导航,可以在 razor 组件中执行以下操作:

@{
    var returnUrl = $"{navigationManager.BaseUri}{LogoutCallbackUrl}";
    <NavLink class="nav-link" href=@($"Logout?redirectUri={returnUrl}") Match="NavLinkMatch.Prefix" />
}

where LogoutCallbackUrl will be the page for the redirect was sign out has completed.其中LogoutCallbackUrl将是重定向的页面,注销已完成。

The last step is to make sure that the logout callback redirect page allows for anonymous access.最后一步是确保注销回调重定向页面允许匿名访问。 So if the callback is a razor component, this would be done by adding the following:因此,如果回调是一个 razor 组件,则可以通过添加以下内容来完成:

@attribute [Microsoft.AspNetCore.Authorization.AllowAnonymous]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM