【问题标题】:How to manage authentication and authroization in .NET Core 2.0 with Identity & Entity Framework如何使用 Identity and Entity Framework 在 .NET Core 2.0 中管理身份验证和授权
【发布时间】:2018-08-21 20:28:24
【问题描述】:

简介

过去几天我一直在从事小型宠物项目,目标是学习 .NET Core 2.0 以及由 Entity Framework Core 支持的 Identity。它是一个典型的“WebAPI”类型项目,具有基于 cookie 的身份验证和基于声明的授权。它被某些客户端应用程序 (SPA) 使用。

代码

在 Startup.cs 中以这种方式配置授权和身份验证流程

services
    .AddIdentity<ApplicationUser, IdentityRole> ()
    .AddEntityFrameworkStores<ApplicationDbContext> ()
    .AddDefaultTokenProviders ();

services
    .AddAuthentication (sharedOptions => {
        sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie ();

我的登录控制器操作如下所示:

[HttpPost]
[Route ("login")]
public async Task<IActionResult> Login ([FromBody] LogInCredentialsModel credentials) {
    // Get User for given UserName
    var user = await userManager.Users.FirstOrDefaultAsync (p => p.UserName == credentials.UserName);

    //User not found
    if (user == default (ApplicationUser))
        return StatusCode (400);

    // Check if password is correct
    var result = await signInManager.PasswordSignInAsync (user, credentials.Password, true, false);

    if (result.Succeeded) {
        //Basic claims with Name and Email
        List<Claim> claims = new List<Claim> {
            new Claim (ClaimTypes.Name, user.UserName),
            new Claim (ClaimTypes.Email, user.Email)
        };

        var userRoles = await this.GetUserRoles (user); // Custom helper method to get list of user roles

        // Add Role claims
        foreach (var role in userRoles) {
            claims.Add (new Claim (ClaimTypes.Role, role));
        }

        ClaimsIdentity identity = new ClaimsIdentity (claims, CookieAuthenticationDefaults.AuthenticationScheme);
        ClaimsPrincipal principal = new ClaimsPrincipal (identity);

        // Sign in using cookie scheme
        await HttpContext.SignInAsync (CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties {
            IsPersistent = true,
        });

        return Ok ();
    } else {
        return StatusCode (400);
    }
}

问题

  1. 这些声明将存储在加密的用户 cookie 中。这意味着,如果我从用户那里删除了一些声明并且他没有重新登录,他仍然会分配旧的声明。我该如何防止呢?还是我误解了设计?
  2. 用户将用户名和密码传递给登录路径,然后用于登录。在我的代码中,我必须首先找到具有给定用户名的用户(第一次 db 命中),然后尝试使用 SignInManager 使用密码登录(第二次db 命中),读取角色(第 3 次 db 命中)以构建 ClaimsPrincipal,然后使用 HttpContext.SignInAsync 以便创建具有正确声明的用户 cookie。我个人觉得我遗漏了一些东西,结果我的代码过于复杂,至少一个数据库查询可以保存在这里。如何改进这部分?

【问题讨论】:

  • 那么您要问哪个问题... 1. 还是 2.?请每个发布的问题提出一个问题。
  • 这是同一机制的两个方面,因此它们被包含在单个问题中。快速浏览一下 meta.stackoverflow.com 让我相信这是允许的。
  • @wirher 你为什么要这样手动构建ClaimsPrincipal?应该由框架为您处理。
  • @trailmax 感谢您的意见。我这样做是为了使我的跟踪和错误代码工作。为什么框架没有在我的实例中处理它?在下面克里斯普拉特的回答下查看我的评论。

标签: c# asp.net-identity asp.net-core-2.0 asp.net-core-webapi


【解决方案1】:

您的两个问题的答案都很基本,所以也许您应该花更多时间阅读文档以更好地处理这个问题。也就是说:

  1. 是的。你是对的。当您更改声明时,您也应该将用户注销。然后,您可以选择让他们再次自动登录,无需用户干预,或提示用户重新登录(取决于您的个人安全偏好)。

  2. 您为什么要手动执行所有这些操作?您只需要:

    var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
    

    这会自动对密码进行哈希处理,尝试使用该用户名(电子邮件地址)和哈希密码检索用户,然后创建一个包含所有这些信息的 ClaimsPrincipal(如果成功)。一个就完成了。

【讨论】:

  • 问题是当我使用 SignInManager 登录时,我看到设置了一些 cookie,但是 this.User.Identity.IsAuthenticated 返回 false 并且 [Authorize] 属性阻止客户端访问路由。
  • 好的,我想我发现我的代码有什么问题。在我注册服务的启动代码中,我调用 AddAuthentication (...) 和 AddCookie(...) 来配置没有身份的 cookie 身份验证。当我删除这部分时,一切都开始像宣传的那样工作。谢谢克里斯,你把我推向了正确的方向。
猜你喜欢
  • 1970-01-01
  • 2020-07-12
  • 2022-06-13
  • 2014-12-11
  • 2014-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-20
相关资源
最近更新 更多