无法执行 Cookie 身份验证:SignInAsync 和 AuthenticateAsync 不成功

问题描述 投票:0回答:3

我正在尝试构建一个非常简单的游乐场服务器,以供我研究一些 ASP.NET Core 身份验证/授权概念。基本上是一个带有一个非常简单的控制器的网络应用程序,可以使用 Postman 进行测试。

我提出了代码的缩小版本,由单个登录端点组成,该端点将使用 Cookie 身份验证对用户进行身份验证(不需要凭据),如下所示:

[ApiController]
public class MyController : ControllerBase
{
    [HttpGet("/login")]
    public async Task<IActionResult> Login()
    {
        var claims = new[] { new Claim("name", "bob") };
        var identity = new ClaimsIdentity(claims);
        var principal = new ClaimsPrincipal(identity);

        await HttpContext.SignInAsync(principal);
        return Ok();
    }
}

问题是对

HttpContext.SignInAsync()
的调用引发了以下异常:

System.InvalidOperationException: SignInAsync when principal.Identity.IsAuthenticated is false is not allowed when AuthenticationOptions.RequireAuthenticatedSignIn is true.
   at Microsoft.AspNetCore.Authentication.AuthenticationService.SignInAsync(HttpContext context, String scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
   at MyController.Login() in C:\Users\vinic\Desktop\TEMP\TestesAuthorization\Controllers\MyController.cs:line 18

然后我尝试通过调用

HttpContext.SignInAsync()
来替换
HttpContext.AuthenticateAsync()
,以便我可以在尝试再次调用
SignInAsync()
之前对用户进行身份验证:

[HttpGet("/login")]
public async Task<IActionResult> Login()
{
    var authResult = await HttpContext.AuthenticateAsync();
    if (authResult.Succeeded == false)
        return StatusCode(500, "Failed to autenticate!");
    return Ok();
}

但在这种情况下,

AuthenticateAsync()
结果始终返回失败(
authResult.Succeeded
= false),并且稍后对
HttpContext.SignInAsync()
的调用将失败,并出现与之前相同的 InvalidOperationException。通过启用“Trace”级别日志记录,对 AuthenticateAsync() 的调用仅记录以下(不是很有帮助)的信息:

dbug: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[9]
      AuthenticationScheme: Cookies was not authenticated.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler: Debug: AuthenticationScheme: Cookies was not authenticated.

我的项目针对

net5.0
框架,没有外部/显式依赖项,这是我正在使用的 Startup 类:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie();
    }


    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IConfiguration configs)
    {
        app.UseRouting();
        app.UseAuthentication();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

我知道我一定错过了一些非常基本的东西。我也不确定我所依据的文档是否实际上是.NET 5.0的最新版本。

为什么 cookie 验证 (

HttpContext.SignInAsync()
/
HttpContext.AuthenticateAsync()
) 失败?

c# asp.net-core cookies .net-5
3个回答
35
投票

这是自 Asp.Net Core 3.0 Preview 6 以来的一项重大更改。文档位于此处 https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnetcore#identity-signinasync-throws-exception- for-unauthenticated-identity,但它不包含重大更改的动机。

真正的动机在这里: https://github.com/dotnet/aspnetcore/issues/9255

简而言之,您需要显式指定 auth 方案:

new ClaimsIdentity(claims, /*Explicit*/CookieAuthenticationDefaults.AuthenticationScheme)

我遇到了同样的问题,这个改变对我的情况有所帮助。


6
投票

只是为了以 Dmitriy 的答案为基础,这里是一个工作登录的片段(.NET 5.0,可能适用于 3.0 及更高版本):

var claims = new List<Claim>
{
    // example claims from external API
    new Claim("sub", userId), 
    new Claim(ClaimTypes.Name, username)
};

var claimsIdentity = new ClaimsIdentity(
                claims, CookieAuthenticationDefaults.AuthenticationScheme);
var signIn = HttpContext.SignInAsync(new ClaimsPrincipal(claimsIdentity),
                _userService.AuthenticationOptions(model.RememberMe));

0
投票

ClaimsIdentity(IEnumerable<Claim>? claims, string? authenticationType)
中第二个参数是
authenticationType
,值不一定是CookieAuthenticationDefaults.AuthenticationScheme。

authenticationType
的值是“用于建立此身份的身份验证方法”,并且可以是任何有意义的值 - 与 CookieAuthenticationDefaults.AuthenticationScheme 的值无关。

例如,如果您有外部身份验证(Google 或其他),您的身份验证方案仍然是 cookie,但

authenticationType
值可能只是“google 密码”。

© www.soinside.com 2019 - 2024. All rights reserved.