ASP.NET Core WebApi 身份验证

时间:2021-01-26 18:09:44

标签: c# asp.net-core authentication asp.net-web-api asp.net-identity

好的,首先让我说我对 ASP.NET Core 和一般的 Web 开发还比较陌生。虽然我过去做过一些小项目。
我正处于迷失方向,无法弄清楚我的问题是什么。我希望你至少能指出我正确的方向。

我想做什么

TLDR:使用 WebApi 对 Blazor 应用进行身份验证和授权

我想创建一个由 ASP.Core 5 应用程序托管的 Blazor WebAssembly 应用程序。业务逻辑将由另一个 WebApi 执行。

所以我有 3 个相关的项目:

  • WebClient(前端)
  • WebHost(WebClient 主机)
  • WebApi(后端)

WebHost 只是要托管在 docker 容器中,该容器将在反向代理之后运行。所以我所做的一切都是在本地的 http 上运行。

Blazor 通过 WebApi ApiController (REST Api) 与后端通信。

前端有一些区域需要用户身份验证和授权。 WebApi 旨在解决这个问题。

我的问题就在这里。


我做了什么

我已使用自定义的 IdentityUserIdentityRoleIUserStore 等将 IdentityService 添加到我的 WebApi。
当我使用 Swagger 测试我的 Api 时,注册、登录、更改密码等工作正常。

我的问题:WebApi 不记得登录。这意味着我可以登录并且我的 SignInManager 告诉我一切都很好,但是当我下次调用端点时控制器将不知道有关用户的任何信息。
当我成功调用登录端点时,浏览器中存储了一个 cookie。当我检查后端上的 HttpContext 时,我可以看到 cookie。


实施详情

我尽量保持片段简短并删除不相关的部分。

启动配置方法

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

app.UseSwagger();
app.UseSwaggerUI(...);

app.UseEndpoints(x => x.MapControllers());

启动ConfigureServices方法

services.AddControllers();
services.AddSwaggerGen(...);

services.AddScoped<IUserManager, AppUserManager>();
services.AddScoped<ISignInManager, AppSignInManager>();
services.AddTransient<IUserStore<AppUser>, AppUserStore>();
services.AddTransient<IRoleStore<AppRole>, AppRoleStore>();
services.AddIdentity<AppUser, AppRole>()
        .AddDefaultTokenProviders();
services.Configure<IdentityOptions>(...);

services.AddHttpContextAccessor();
services.AddAuthentication();
services.AddAuthorization();

身份验证控制器端点

[HttpPost(nameof(Login))]
public async Task<IActionResult> Login([FromBody] LoginUserCommand command)
{
    // I've abstracted my logic into a Mediator Command
    // but simplified this is just
    // SignInManager.PasswordSignInAsync(user, pass, rememberMe)
    // ClaimsFactory.CreateAsync(user)
    var result = await Mediator.Send(command); 

    if (result.Succeeded)
    {
        // I've tried the following 2 methods to store the ClaimsPrincipal with no success
        await HttpContext.SignInAsync(result.Data);
        var signInResult = SignIn(result.Data); // positive result

        return Ok(...);
    }

    return BadRequest(...);
}

swagger 发出的 POST 请求

curl -X POST "http://localhost:4000/_api/v1/Auth/Login"
     -H "accept: */*"
     -H "Content-Type: application/json"
     -d "{\"password\":\"P4$$w0rd\",\"rememberMe\":true,\"username\":\"admin\"}"

存储在浏览器中的 Cookie

Name: Identity.External
Content: CfDJ8EGl21FYRChCvuGjMRYlEqvNaCBZMxNrNE8D [...]
Domain: localhost
Path: /
Created: 5 minutes ago
Expires: When the browsing session ends

1 个答案:

答案 0 :(得分:0)

尝试在使用身份验证服务时添加 cookie 方案:

        services.AddAuthentication(options =>
        {
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        }).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme);

然后,当您登录时使用相同的方案:

        var claimsIdentity = new ClaimsIdentity(
            claims, CookieAuthenticationDefaults.AuthenticationScheme);

        var authProperties = new AuthenticationProperties
        {
            IsPersistent = true,
        };

        await httpContext.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(claimsIdentity),
            authProperties);