好的,我尝试在自定义AuthenticationStateProvider中检测请求源。以下是我的尝试:
- Session Id不起作用,因为由于WebSocket,同一浏览器中的每个请求都会检索到全新的ID。
- 显然HttpContext.Connection.Id不起作用,因为它对于每个刷新页面都会更改。
- builder.Services.AddSingleton不起作用,因为它在整个应用程序生命周期中保持数据。
- 所以您知道,无论是浏览器还是计算机,builder.Services.AddTransient和builder.Services.AddScoped也会在每个单独的请求中更改。
- 嗯,我认为HttpContext.Connection.Ip不能使用,因为它使用与同一局域网中的PC相同的IP地址。
那么我如何区分哪个请求属于哪个PC或浏览器? 如何在我的方式中保持已登录用户,而不使用Blazor的身份验证?
这里是示例代码
/// <summary>
/// https://learn.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-6.0#authenticationstateprovider-service
/// https://learn.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-6.0#implement-a-custom-authenticationstateprovider
/// https://www.indie-dev.at/2020/04/06/custom-authentication-with-asp-net-core-3-1-blazor-server-side/
/// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-6.0
/// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-6.0#session-state
/// https://learn.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-6.0&pivots=server#where-to-persist-state
/// </summary>
public class CustomAuthStateProvider : AuthenticationStateProvider
{
private IHttpContextAccessor context;
static ConcurrentDictionary<string, ClaimsPrincipal> logins = new ConcurrentDictionary<string, ClaimsPrincipal>();
public CustomAuthStateProvider(IHttpContextAccessor context)
{
this.context = context;
}
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
if (logins.TryGetValue(context.HttpContext.Session.Id, out var p))
{
return Task.FromResult(new AuthenticationState(p)); // <---- The debugger never stops here becuse Session Id is changes for every reqquest
}
else
{
//it will return empty information in real application for force it login
//return Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())));
//This block does not belong here, it will be populated on the Login page in the real application. For now I'm just running it here for testing
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "RandomId"), //It will ger user infos from our custom database. (No MS's Auth Database)
new Claim(ClaimTypes.Role, "A")
}, "Fake authentication type");
var user = new ClaimsPrincipal(identity);
logins[context.HttpContext.Session.Id] = user;
return Task.FromResult(new AuthenticationState(user));
}
}
}