'How to close Authorizing in Blazor AuthorizeRouteView
I have a Server side Blazor project with Net6. I have marked the “Authorizing” in AuthorizeRouteView section of App.razor. When I open the Login page or quickly hit the browser refresh button, the browser content area will flicker。It looks like the login page is displayed first, then “Authorizing” text with the Mainlayout, and finally the login page again。I want AuthorizeRouteView to only display the login page once when it judges that the login page route has no authority 。 Thank you.
My test code is on github [1]: https://github.com/flagshang/MyBlazorApp
***********************Login.razor***********************
@page "/"
@layout LoginLayout
@inject NavigationManager navigationManager
@inject ILocalStorageService localStorage
@inject AuthenticationStateProvider Auth
<form>
<div class="form-group">
<label>UserName:</label>
<div>
<input @bind-value="@UserName">
</div>
</div>
<div>
<label>Password:</label>
<div>
<input @bind-value="@Password">
</div>
</div>
<div>
<div>
<button type="button" @onclick="LoginMethod">Login in</button>
</div>
</div>
</form>
@code {
private string UserName { get; set; }
private string Password { get; set; }
private async Task LoginMethod()
{
//if (UserName == "admin" && Password == "12345")
{
UserName = "admin";
await localStorage.SetItemAsync("token", UserName);
((CustomStateProvider)Auth).MarkUserAsAuthenticated(UserName);
navigationManager.NavigateTo("/index", false);
}
}
}
**********************************************************
***********************LoginLayout.razor****************
@inherits LayoutComponentBase
<div >
@Body
</div>
**********************************************************
***********************index.razor****************
@page "/index"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
**********************************************************
***********************MainLayout.razor****************
@inherits LayoutComponentBase
@inject NavigationManager navigationManager
@inject AuthenticationStateProvider Auth
<PageTitle>MyBlazorApp</PageTitle>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<button type="button" @onclick="LogOutMethod">Login out</button>
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
@code {
private async Task LogOutMethod()
{
((CustomStateProvider)Auth).MarkUserAsLoggedOut();
navigationManager.NavigateTo("/", false);
}
}
**********************************************************
***********************RedirectToLogin.razor****************
@inject NavigationManager NavigationManager
@code
{
protected override void OnAfterRender(bool firstRender)
{
NavigationManager.NavigateTo($"/");
}
}
**********************************************************
***********************App.razor****************
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
@* <Authorizing>
<h1>Authorization in progress</h1>
<p>Only visible while authorization is in progress.</p>
</Authorizing>*@
<NotAuthorized >
<RedirectToLogin/>
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
</NotFound>
</Router>
</CascadingAuthenticationState>
**********************************************************
***********************CustomStateProvider.cs****************
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
namespace MyBlazorApp
{
public class CustomStateProvider : AuthenticationStateProvider
{
private readonly ILocalStorageService _localStorage;
public CustomStateProvider(ILocalStorageService localStorage)
{
_localStorage = localStorage;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
string token = "";
try
{
token = await _localStorage.GetItemAsync<string>("token");
}
catch (Exception ex)
{
}
if (string.IsNullOrWhiteSpace(token))
{
var cptmp = new ClaimsPrincipal(new ClaimsIdentity());
return new AuthenticationState(cptmp);
}
ClaimsIdentity ci = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, token) }, "token");
ClaimsPrincipal cp = new ClaimsPrincipal(ci);
var authState = new AuthenticationState(cp);
NotifyAuthenticationStateChanged(Task.FromResult(authState));
return new AuthenticationState(cp);
}
public void MarkUserAsAuthenticated(string token)
{
var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, token) }, "token"));
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);
}
}
}
**********************************************************
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
