我有自定义AuthenticationStateProvider在我的Blazor WebAssembly应用程序,它不调用GetAuthenticationStateAsync方法在页面刷新,所以如果用户登录,然后他们手动刷新页面claimsprinprincipal是AuthenticationState不填充,所以用户不能被授权。我使用的是JWT保存在cookie中进行验证,cookie在页面刷新后仍然存在,应用程序只是不调用GetAuthenticationStateAsync(如果我正确学习了blazor,它应该在页面刷新)。
这是我的自定义AuthenticationStateProvider:
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly HttpClient _httpClient;
public CustomAuthenticationStateProvider(
IHttpClientFactory httpClientFactory)
{
_httpClient = httpClientFactory.CreateClient("APIClient");
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
//TODO get token from cookie
var savedToken = "";
if (string.IsNullOrWhiteSpace(savedToken))
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(savedToken), "jwt")));
}
public void MarkUserAsAuthenticated(string email)
{
var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, email) }, "apiauth"));
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);
}
}
编辑:它一直在调用GetAuthenticationStateAsync方法,这只是令人困惑,因为我在调试器中,它从未在该方法中击中我的断点,这是我看到其他人的问题(仍然不确定为什么)。
这取决于您调用GetAuthenticationStateAsync
的位置。
在BlazorHero项目中,此调用存在于MainLayout.razor:
</NotAuthorized>
<Authorized>
@(LoadDataAsync())
<MudLayout RightToLeft="@_rightToLeft">
在<<p> strong> MainLayout.razor.cs :private async Task LoadDataAsync()
{
var state = await _stateProvider.GetAuthenticationStateAsync();
var user = state.User;
if (user == null) return;
所以我认为你需要检查它是在哪里被调用的
MainLayout在每次加载页面时呈现。
一个更好的解决方案(更简洁)是在AfterRender
中添加如下代码:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await LoadDataAsync();
}
}