我创建了一个自定义AuthenticationStateProvider,用于将用户设置为已认证。 第一次登录时有效,但是在刷新页面时,该用户没有再次获得授权,而是被重定向到登录页面。 我在启动中设置了CookieAuthentication,但这没有帮助。
这是我的启动代码:
public void ConfigureServices(IServiceCollection services)
{
try
{
services.AddRazorPages();
services.AddServerSideBlazor(sb =>
{
sb.DetailedErrors = true;
});
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
});
services.AddAuthentication(
CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie();
services.AddBlazoredLocalStorage();
services.AddScoped<IUserService, UserService>();
//services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
services.AddScoped<CustomAuthenticationStateProvider>();
services.AddScoped<AuthenticationStateProvider>(provider => provider.GetRequiredService<CustomAuthenticationStateProvider>());
services.AddScoped<IAppStateService, AppStateService>();
services.AddHttpContextAccessor();
services.AddScoped<HttpContextAccessor>();
services.AddHttpClient();
services.AddScoped<HttpClient>();
services.AddScoped<SpinnerService>();
//services.AddScoped<BlazorDisplaySpinnerAutomaticallyHttpMessageHandler>();
//services.AddSingleton(sp =>
//{
// BlazorDisplaySpinnerAutomaticallyHttpMessageHandler blazorDisplaySpinnerAutomaticallyHttpMessageHandler = sp.GetRequiredService<BlazorDisplaySpinnerAutomaticallyHttpMessageHandler>();
// HttpMessageHandler handler = sp.GetService<HttpMessageHandler>();
// blazorDisplaySpinnerAutomaticallyHttpMessageHandler.InnerHandler = handler;
// HttpClient client = handler != null ? new HttpClient(blazorDisplaySpinnerAutomaticallyHttpMessageHandler) : new HttpClient();
// var uriHelper = sp.GetRequiredService<Microsoft.AspNetCore.Components.NavigationManager>();
// client.BaseAddress = new Uri(uriHelper.BaseUri);
// return client;
//});
services.AddBlazorise(options =>
{
options.ChangeTextOnKeyPress = false; // optional
})
.AddBootstrapProviders()
.AddFontAwesomeIcons();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
try
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseHttpsRedirection();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.ApplicationServices.UseBootstrapProviders()
.UseFontAwesomeIcons();
loggerFactory.AddLog4Net();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
这是CustomAuthenticationStateProvider:
using Inovoo.OcrValidator.Interfaces;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Http;
using NovoValidateWeb.Services;
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.AspNetCore.Authentication.Cookies;
using Blazored.LocalStorage;
using System.Diagnostics;
using System.Threading;
using Microsoft.AspNetCore.Authentication;
namespace NovoValidateWeb.Data
{
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly ISessionService _sessionService;
private readonly IAppStateService _appStateService;
private readonly HttpContextAccessor _context;
private User _authUser;
public IAppStateService AppStateService
{
get;
set;
}
public CustomAuthenticationStateProvider(IAppStateService appStateService, HttpContextAccessor context)
{
_context = context;
_appStateService = appStateService;
_sessionService = _appStateService.SessionService;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
ClaimsIdentity identity;
if (_authUser != null)
{
identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, _authUser.Username),
new Claim("sessionid", _authUser.SessionId.ToString())
}, CookieAuthenticationDefaults.AuthenticationScheme);
}
else
{
identity = new ClaimsIdentity();
}
ClaimsPrincipal user = new ClaimsPrincipal(identity);
return await Task.FromResult(new AuthenticationState(user));
}
public bool MarkUserAsAuthenticated(User currentUser)
{
_authUser = currentUser;
string username = currentUser.Username;
ClaimsIdentity identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, username),
}, CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal user = new ClaimsPrincipal(identity);
SessionPrincipal sessionUser = new SessionPrincipal(username, x =>
{
return true;
}, Guid.Empty);
Debug.Print($"MarkUserAsAuth - Before - Session ID = {currentUser.SessionId} ");
MarkUserAsLoggedOut(username);
Guid sessionId = _sessionService.Login(sessionUser);
currentUser.SessionId = sessionId;
_appStateService.AuthenticatedUser = currentUser;
Debug.Print($"MarkUserAsAuth - After - Session ID = {sessionId} ");
identity.AddClaim(new Claim("sessionid", sessionId.ToString()));
_context.HttpContext.User = user;
_context.HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
user);
_appStateService.Init();
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
return true;
}
public void MarkUserAsLoggedOut(string username)
{
Logout(username);
System.Security.Claims.ClaimsIdentity identity = new ClaimsIdentity();
ClaimsPrincipal user = new ClaimsPrincipal(identity);
}
private void Logout(string username)
{
var session = _sessionService.GetSessionByUserName(username);
if (session != null)
{
Debug.Print($"AuthProvider - Logout - Session ID = {session.SessionId} ");
_sessionService.Logout(session.SessionId);
}
}
}
}