.Net Core IsAuthenticated false,即使我手动使用HttpContext.SignInAsync

StN*_*las 1 c# authentication jwt asp.net-core

我的应用程序使用cookie和承载身份验证:

var membershipService = configuration.GetValue<string>("MembershipService:BaseUri");
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddCookie()
    .AddJwtBearer(opt =>
    {
        opt.Audience = "gateway";
        opt.Authority = membershipService;
        opt.RequireHttpsMetadata = false;
        opt.SaveToken = true;
        opt.Events = new JwtBearerEvents()
        {
            OnTokenValidated = (context) =>
            {
                var accessToken = context.SecurityToken as JwtSecurityToken;
                if (accessToken != null)
                {
                    ClaimsIdentity identity = context.Principal.Identity as ClaimsIdentity;
                    if (identity != null)
                    {
                        identity.AddClaim(new Claim("access_token", accessToken.RawData));
                    }
                }
                return Task.CompletedTask;
            }
        };
});
Run Code Online (Sandbox Code Playgroud)

当我发送access_token标题时,一切正常.

但是如果我在第二个请求(第一个带有授权头)的头中没有令牌发送,似乎User对先前的身份验证一无所知.即使我这样做HttpContext.SignInAsync("Cookies", User),下一个请求,例如在按下F5之后,也没有用户进行身份验证.

我错过了什么?

pok*_*oke 7

首先,除非您实际调用SignInAsynccookie方案,否则不会创建cookie.所以你需要这样做.但仅仅因为用户发送cookie并不意味着cookie方案将运行并尝试对用户进行身份验证.

你这样打电话AddAuthentication:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
Run Code Online (Sandbox Code Playgroud)

这意味着JWT承载认证将是默认的认证方案.因此,当身份验证中间件运行时,它将尝试验证身份验证方案,并且仅对此进行身份验证.如果您有多个身份验证方案,则只有默认身份验证方案才会实际尝试对用户进行身份验证.否则,如果多个方案可以验证用户,则会发生冲突.

因此,在您的情况下,用户未经过身份验证,因为cookie身份验证方案根本没有运行.你应该考虑你的默认方案应该是什么.如果您只想将承载令牌用作"登录",则使用cookie身份验证方案作为默认值是有意义的.然后,您可以提供需要承载方案的登录操作,然后在cookie方案中签名:

[Authorize(AuthenticationSchemes=JwtBearerDefaults.AuthenticationScheme)]
public async Task<IActionResult> Login()
{
    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, User);
    return View();
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用您access_tokenAuthorize属性调用该路由,并使该属性触发JWT承载方案的身份验证,并使用该用户使用cookie方案登录.因此后续请求将使用cookie方案(作为默认值)并且将识别用户.

最后请注意,JWT承载认证通常被视为无状态认证方法,并且在每个请求上明确发送令牌被认为是正确的做法.因此,从中生成一个cookie会有点奇怪.