我在应用程序中使用Cookie和承载身份验证。但是我有一种奇怪的行为,我无法解释。
我确实有自定义的中间件,在其中我向Context.Items添加了一些必需的数据。这一切都很好,但在该中间件中,如果用户的承载是空的,则它的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
};
});
我在CreateTicket上使用的临时解决了我的问题
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;
}
....
}
所以我的问题是为什么cookie和oauth不同?为什么如果我的cookie可以访问中间件中的用户,而我的oauth无法访问?
答案 0 :(得分:1)
那是因为调用services.AddIdentity()
时ASP.NET Core身份registers itself as the default authentication scheme handler。
app.UseAuthentication()
后面的中间件收到请求后,将自动调用Identity注册的cookie身份验证处理程序,并使用从身份验证cookie中提取的结果HttpContext.User
填充ClaimsPrincipal
。
使用不记名令牌,这不会发生,因为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;
}
}