我在应用程序中使用了cookie和持有者身份验证。但我有奇怪的行为,我无法解释。
我确实有自定义中间件,我在其中将一些必需的数据添加到上下文中。 一切都很好,但在中间件中,如果它的持有者是空的,但当它的cookie时它可以。
services
.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(OAuthValidationDefaults.AuthenticationScheme,
CookieAuthenticationDefaults.AuthenticationScheme,
"Identity.Application")
.RequireAuthenticatedUser()
.Build();
});
//CookieAuthenticationDefaults.AuthenticationScheme
services.AddAuthentication()
.AddExternalAuthProviders(Configuration)
.AddFlymarkOpenIdConnectServer()
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = "/Identity/Account/LogIn";
options.SlidingExpiration = true;
options.Events.OnRedirectToLogin = OnRedirectToLogin;
})
.AddOAuthValidation(OAuthValidationDefaults.AuthenticationScheme,
o=>o.Events.OnCreateTicket = OnCreateTicket);
services.ConfigureApplicationCookie(config =>
{
config.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = OnRedirectToLogin
};
});
临时我在创建票证上使用,可以解决我的问题
private async Task OnCreateTicket(CreateTicketContext arg)
{
if (arg.HttpContext.Items[FlymarkWeb.CurrentUserKey] == null && arg.Identity.IsAuthenticated)
{
var db= (FlymarkContext) arg.HttpContext.RequestServices.GetService(typeof(FlymarkContext));
arg.HttpContext.Items[FlymarkWeb.CurrentUserKey] =
await db.Users.FirstOrDefaultAsync(u => u.Id == arg.Identity.GetUserId());
}
}
和中间件
public async Task Invoke(HttpContext httpContext, FlymarkContext context, DomainService _sourceDomainService)
{
if (httpContext.Items[FlymarkWeb.CurrentUserKey] == null)
{
httpContext.Items[FlymarkWeb.CurrentUserKey] = httpContext.User.Identity.IsAuthenticated
? await context.Users.FirstOrDefaultAsync(u => u.Id == httpContext.User.GetUserId())
: null;
}
....
}
所以我的问题是为什么饼干和oauth不同?为什么如果它的cookie我可以在中间件中访问用户,如果它的oauth我不能?
这是因为当您调用services.AddIdentity()
时 ASP.NET 核心标识将自身注册为默认身份验证方案处理程序。
当收到请求时,app.UseAuthentication()
后面的中间件会自动调用 Identity 注册的 cookie 身份验证处理程序,并用从身份验证 cookie 中提取的结果ClaimsPrincipal
填充HttpContext.User
。
对于持有者令牌,不会发生这种情况,因为 OAuth 验证处理程序不会将自身注册为默认身份验证处理程序(这是您必须在 2.0 中手动和显式执行的操作)。
要将其配置为默认处理程序,您可以这样做:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OAuthValidationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OAuthValidationDefaults.AuthenticationScheme;
});
或者,您可以自己直接执行身份验证操作,而不是依赖 HttpContext.User
。例如:
public async Task Invoke(HttpContext httpContext, FlymarkContext context, DomainService _sourceDomainService)
{
if (httpContext.Items[FlymarkWeb.CurrentUserKey] == null)
{
var principal = (await httpContext.AuthenticateAsync(OAuthValidationDefaults.AuthenticationScheme))?.Principal;
httpContext.Items[FlymarkWeb.CurrentUserKey] = principal?.Identity != null && principal.Identity.IsAuthenticated
? await context.Users.FirstOrDefaultAsync(u => u.Id == principal.GetUserId())
: null;
}
}