Cookie 身份验证无法与 JWT 身份验证正常工作 ASP.NET CORE

Cookie authentication not working properly with JWT authentication ASP.NET CORE

我正在练习使用 ASP.NET CORE 编写 Web 应用程序,但我遇到了 Identity 问题。我尝试在网上搜索是否有其他人遇到过这样的问题,但无济于事。

我构建了一个简单的网络 api,它使用 JWT 进行身份验证并且一切正常。但我还需要让用户能够使用表单登录,即 cookie 身份验证。以下是我配置服务的方法。

private static void ConfigureJwt(IConfiguration configuration, IServiceCollection services)
        {
            services.AddSingleton<JwtSettings>();
            services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                }).AddCookie( conf =>
                {
                    conf.SlidingExpiration = true;
                    conf.LoginPath = "/account/login";
                    conf.LogoutPath = "/account/logout";
                })
                .AddJwtBearer(options =>
                {
                    options.SaveToken = true;
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey =
                            new SymmetricSecurityKey(Encoding.ASCII.GetBytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")),
                        ValidateAudience = false,
                        ValidateIssuer = false,
                        RequireExpirationTime = false,
                        ValidateLifetime = true,
                        ClockSkew = TimeSpan.Zero,
                        ValidateActor = true

                    };
                });
        }

因此,由于 DefaultChallengeScheme 设置为 "JwtBearerDefaults.AuthenticationScheme" 我假设,如果我想授权使用 cookie 身份验证登录的用户,我应该只在该特定控制器方法中指定 cookie 身份验证方案如下所示。

[Route("[controller]/[action]")]
    [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
    public class HomeController : Controller
    {
        // GET
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }
    }

但我总是被重定向到登录页面。

我让它工作的唯一方法是删除默认身份验证设置

private static void ConfigureJwt(IConfiguration configuration, IServiceCollection services)
        {
            var jwtSettings = new JwtSettings();
            configuration.Bind(nameof(JwtSettings), jwtSettings);
            services.AddSingleton<JwtSettings>();
            services.AddAuthentication()
                .AddCookie( conf =>
                {
                    conf.SlidingExpiration = true;
                    conf.LoginPath = "/account/login";
                    conf.LogoutPath = "/account/logout";
                })
                .AddJwtBearer("jwt", options =>
                {
                    options.SaveToken = true;
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey =
                            new SymmetricSecurityKey(Encoding.ASCII.GetBytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")),
                        ValidateAudience = false,
                        ValidateIssuer = false,
                        RequireExpirationTime = false,
                        ValidateLifetime = true,
                        ClockSkew = TimeSpan.Zero,
                        ValidateActor = true

                    };
                });
        }

然后在 cookie 相关路由上使用正常的 [Authorize] 属性

[Route("[controller]/[action]")]
    [Authorize]
    public class HomeController : Controller
    {
        // GET
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }
    }

然后在我所有的 API 路由中,我指定了 JWT 的身份验证方案

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
        [HttpGet(ApiRoutes.Posts.GetAll)]
        public async Task<IActionResult> GetAll()
        {
            var posts = await _postService.GetAllAsync();
            return Ok(posts);
        }

所以我的问题是,为什么初始配置不起作用?而且由于我的应用程序主要使用 JWT 身份验证,我希望它成为默认的身份验证方案,并且只在很少使用的控制器方法中指定 cookie 身份验证方案。这可能吗?如果是,我该如何实现?

经过更多挖掘,我偶然发现了这个 thread,它回答了我的问题。

我误解了身份验证在使用身份的 asp.net 核心应用程序中的工作原理。 当您使用身份验证和登录用户时,使用的默认身份验证方案称为 "Identity.Applicaiton" 而不是 "Cookies"。

var result = await _signInManager.PasswordSignInAsync(loginModel.Email, loginModel.Password, true, false);

                if (result.Succeeded)
                {
                    return LocalRedirect("/home/index");
                }

但是如果你想使用 "Cookies" 身份验证方案,你必须使用 HttpContext.SignInAsync 验证和登录用户,如下所示,并明确地 select "Cookies" 作为您的身份验证方案。

var claims = new[]
                {
                    new Claim("email", user.Email),
                };
                var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
                    new ClaimsPrincipal(identity));