Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/102.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用Identity&;在.NET Core 2.0中管理身份验证和身份验证;实体框架_C#_Asp.net Identity_Asp.net Core 2.0_Asp.net Core Webapi - Fatal编程技术网

C# 如何使用Identity&;在.NET Core 2.0中管理身份验证和身份验证;实体框架

C# 如何使用Identity&;在.NET Core 2.0中管理身份验证和身份验证;实体框架,c#,asp.net-identity,asp.net-core-2.0,asp.net-core-webapi,C#,Asp.net Identity,Asp.net Core 2.0,Asp.net Core Webapi,导言 在过去的几天里,我一直在从事一个小型pet项目,目标是学习.NET Core 2.0,其身份由Entity Framework Core支持。它是一个典型的“WebAPI”类型的项目,具有基于cookie的身份验证和基于声明的授权。它被一些客户端应用程序(SPA)使用 代码 在Startup.cs中以这种方式配置授权和身份验证流 services .AddIdentity<ApplicationUser, IdentityRole> () .AddEntityF

导言

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

代码

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

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

services
    .AddAuthentication (sharedOptions => {
        sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie ();
服务
.额外性()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
服务
.AddAuthentication(sharedOptions=>{
sharedOptions.DefaultAuthenticateScheme=CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultSignenscheme=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);
    }
}
[HttpPost]
[路线(“登录”)]
公共异步任务登录([FromBody]LoginRedentialsModel凭据){
//获取给定用户名的用户
var user=await userManager.Users.FirstOrDefaultAsync(p=>p.UserName==credentials.UserName);
//找不到用户
如果(用户==默认值(应用程序用户))
返回状态码(400);
//检查密码是否正确
var result=await-signInManager.PasswordSignInAsync(用户、凭据、密码、true、false);
if(result.successed){
//带有姓名和电子邮件的基本索赔
清单索赔=新清单{
新索赔(ClaimTypes.Name、user.UserName),
新索赔(ClaimTypes.Email、user.Email)
};
var userRoles=wait this.GetUserRoles(user);//获取用户角色列表的自定义帮助器方法
//添加角色声明
foreach(userRoles中的var角色){
添加(新索赔(ClaimTypes.Role,Role));
}
ClaimsIdentity identity=新的ClaimsIdentity(claims,CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal principal=新的ClaimsPrincipal(标识);
//使用cookie方案登录
等待HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,主体,新AuthenticationProperties{
ispersist=true,
});
返回Ok();
}否则{
返回状态码(400);
}
}
问题

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

  • 你的两个问题的答案都很基本,所以也许你应该花更多的时间和文档在一起,以便更好地处理这个问题。也就是说:

  • 对。你说得对。更改声明时,还应注销用户。然后,您可以选择再次自动登录,而无需用户干预,或者提示用户重新登录(取决于您的个人安全偏好)

  • 你为什么要手工做这些?您所需要的只是:

    var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
    
    自动散列密码,尝试使用该用户名(电子邮件地址)和散列密码检索用户,然后创建一个包含所有信息的
    ClaimsPrincipal
    ,如果成功。一劳永逸


  • 那么你在问什么问题。。。1.还是2。?请每个问题一个问题。这是同一机制的两个方面,这就是为什么它们包含在一个问题中。快速浏览meta.stackoverflow.com让我相信这是允许的。@你为什么要用这种方式手工构建
    ClaimsPrincipal
    ?这应该由框架为您处理。@trailmax感谢您的输入。我这样做是为了让我的跟踪和错误代码正常工作。为什么框架没有在我的实例中处理它?请参阅下面Chris Pratt回答下的我的评论。问题是,当我使用SignInManager登录时,我看到设置了一些cookie,但this.User.Identity.IsAuthenticated返回false,[Authorize]属性阻止客户端访问路由。好的,我想我发现了代码的问题所在。在注册服务的启动代码中,我调用AddAuthentication(…)和AddCookie(…),它们用于配置无标识的cookie身份验证。当我移除这部分时,一切都开始正常工作。谢谢克里斯,你把我推向了正确的方向。