Blazor webassembly - IdentityServer EventSink and HttpContex



我正在开发一个Blazor webassembly应用程序,在 ASP.NET Core 3.1中使用IdentityServer。 由于身份服务器处理所有登录,注销,注册,...事件,我正在尝试捕获这些事件以获取有关用户的一些信息。

需要明确的是,我正在尝试记住登录日期,并捕获新用户注册以自动赋予他们一些角色。

这是我在启动类中使用的所有服务:

services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.Configure<IdentityOptions>(options =>
options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options => {
options.IdentityResources["openid"].UserClaims.Add("name");
options.ApiResources.Single().UserClaims.Add("name");
options.IdentityResources["openid"].UserClaims.Add("role");
options.ApiResources.Single().UserClaims.Add("role");
});
// Need to do this as it maps "role" to ClaimTypes.Role and causes issues
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");
services.AddAuthentication()
.AddIdentityServerJwt();

我已经实现了IEventSink模式(http://docs.identityserver.io/en/stable/topics/events.html(:

public class IdentityServerEventSink : IEventSink
{
private readonly UserManager<ApplicationUser> userManager;
private readonly IHttpContextAccessor httpContextAccessor;
public IdentityServerEventSink(UserManager<ApplicationUser> userManager, IHttpContextAccessor httpContextAccessor)
{
this.userManager = userManager;
this.httpContextAccessor = httpContextAccessor;
}
public async Task PersistAsync(Event @event)
{
if (@event.Id.Equals(EventIds.ClientAuthenticationSuccess))
{
var identity = httpContextAccessor.HttpContext.User;
var id = httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
var user = await userManager.Users.FirstOrDefaultAsync(u => u.Id == id);
}
}
}

在启动中.cs :

services.AddHttpContextAccessor();
services.AddTransient<IEventSink, IdentityServerEventSink>();

但是当我进入 ClientAuthenticationSuccess 事件时,身份始终是匿名的。

我也尝试了中间件,但我有同样的问题:

app.Use(async (context, next) =>
{
await next.Invoke();
//handle response
//you may also need to check the request path to check whether it requests image
if (context.User.Identity.IsAuthenticated)
{
var userName = context.User.Identity.Name;
//retrieve uer by userName
using (var dbContext = context.RequestServices.GetRequiredService<ApplicationDbContext>())
{
var user = dbContext.Users.Where(u => u.UserName == userName).FirstOrDefault();
user.LastLogon = System.DateTime.Now;
dbContext.Update(user);
dbContext.SaveChanges();
}
}
});

你有什么想法吗? 我听说 HttpContextAccessor 在 Blazor 中是个坏东西。

好的,所以更新后中间件委托工作!

app.Use(async (context, next) =>
{
await next.Invoke();
if (context.User.Identity.IsAuthenticated)
{
var userName = context.User.Identity.Name;
using (var dbContext = context.RequestServices.GetRequiredService<ApplicationDbContext>())
{
var user = dbContext.Users.Where(u => u.UserName == userName).FirstOrDefault();
if (user != null)
{
user.LastLogon = System.DateTime.Now;
user.LastIpAddress = context.Connection?.RemoteIpAddress?.ToString();
dbContext.Update(user);
dbContext.SaveChanges();
}
}
}
});

只要小心应用程序.use的顺序...在配置方法中!您需要在app.UseIdentityServer(); app.UseAuthentication(); app.UseAuthorization();之后添加此内容

但不幸的是,来自IdentityServer的EventSink仍然无法正常工作,httpContextAccessor.HttpContext.User.Identity始终是匿名的。

相关内容

  • 没有找到相关文章

最新更新