如何在ASP.NET MVC 5中实现自定义身份验证。

11 浏览
0 Comments

如何在ASP.NET MVC 5中实现自定义身份验证。

我正在开发一个ASP.NET MVC 5应用程序。我有一个现有的数据库,我从中创建了我的ADO.NET实体数据模型。

该数据库中有一个包含“用户名”和“密码”列的表,我想使用它们来实现Webapp的身份验证和授权;由于客户的要求,我不能创建任何其他数据库、表或列,也不能使用标准的Identity身份验证。

我不需要管理注册、密码更改或其他内容:只需使用密码和用户名登录。

我该如何做到这一点?

0
0 Comments

自定义身份验证在ASP.NET MVC 5中的实现方法

在ASP.NET MVC 5中,可以实现自定义身份验证。身份验证和授权部分可以独立使用。如果您有自己的身份验证服务,可以直接使用OWIN的授权部分。假设您已经有一个UserManager对象,它可以验证用户名和密码。您可以在登录操作的后台代码中编写以下代码:

[HttpPost]
public ActionResult Login(string username, string password)
{
    if (new UserManager().IsValid(username, password))
    {
        var ident = new ClaimsIdentity(
          new[] { 
              // 添加以下2个声明只是为了支持默认的防伪提供程序
              new Claim(ClaimTypes.NameIdentifier, username),
              new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
              new Claim(ClaimTypes.Name,username),
              // 如果有角色,可以选择添加角色
              new Claim(ClaimTypes.Role, "RoleName"),
              new Claim(ClaimTypes.Role, "AnotherRole"),
          },
          DefaultAuthenticationTypes.ApplicationCookie);
        HttpContext.GetOwinContext().Authentication.SignIn(
           new AuthenticationProperties { IsPersistent = false }, ident);
        return RedirectToAction("MyAction"); // 验证成功
    }
    // 无效的用户名或密码
    ModelState.AddModelError("", "invalid username or password");
    return View();
}

UserManager可以是这样的:

class UserManager
{
    public bool IsValid(string username, string password)
    {
         using(var db=new MyDbContext()) // 使用您自己的DbConext
         {
             // 为了简单起见,我使用明文密码,实际上需要实现哈希和盐处理技术   
             return db.Users.Any(u=>u.Username==username 
                 && u.Password==password); 
         }
    }
}

最后,您可以通过在操作或控制器上添加Authorize特性来保护您的操作或控制器。

[Authorize]
public ActionResult MySecretAction()
{
    // 所有授权用户都可以使用此方法
    // 通过调用HttpContext.User,我们可以访问当前用户主体
}
[Authorize(Roles="Admin")]
public ActionResult MySecretAction()
{
    // 只有管理员用户可以访问此方法
} 

如果您在这个示例中使用Authorize注解,也是可以的。只需将Authorize特性添加到您要限制的操作或控制器上即可。同时,您还可以在这个问题的其他答案中找到更多类似的解决方法。

希望你知道,你的GitHub示例(用于tokenauth)解决了我的问题,非常感谢!如果可以的话,我愿意给你的示例点赞1000次!

所需的NuGet包:Microsoft.AspNet.Identity.Core、Microsoft.AspNet.Identity.Owin、Microsoft.Owin、Microsoft.Owin.Host.SystemWeb、Microsoft.Owin.Security、Microsoft.Owin.Security.Cookies、Microsoft.Owin.Security.OAuth、Owin

我希望你对这个问题开放悬赏,这样我们就可以给你+1000。请将这个问题发布到博客上,以便搜索引擎可以找到这个解决方法。这是一个非常简单和优雅的解决方案。我花了两天时间研究OWIN和OAuth2提供程序,但是我无法连接它们的关系。

请问,为什么在Login代码中需要这个长常量字符串:... new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string") 我检查了代码,没有它也可以正常工作!

这两个声明用于生成和验证防伪令牌。我在之前的问题中讨论过这个问题。

好的,我明白了。但是我认为在startup.cs中使用AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;更好,这样我们只需要在登录时添加NameIdentifier(用户ID)到声明中,而不需要这个身份提供商字符串。硬编码使用这样一个长的常量字符串不好看!

这种方法似乎是OWIN特定的。--在常规的MVC中,我们应该如何实现?--无论如何,仅仅添加NuGet包是不够的,您将遇到一堆有关缺少OwinStartupAttribute和缺少配置设置的代码...

在这个答案中,我假设Identity和OWIN已经存在于项目中,但是问题提出者希望对其进行自定义。安装和实现Identity和OWIN是另一回事,我在其他问题中已经回答过。

嗯,我猜答案试图回答关于OWin特定部分的问题,但是对于阅读这个问题的任何人来说,永远不要像这样实现UserManager类:密码必须经过哈希处理,永远不要存储为明文可读的文本

确实,在现实世界中,密码必须进行哈希处理。我更新了帖子,指出了这一点以消除歧义。谢谢你提到它。

谢谢你的帖子!非常有用!你认为这种方法加上将[ValidateAntiForgeryToken]特性添加到Login方法和哈希和盐处理密码足够安全,可以部署到生产环境吗?提前谢谢!

当然,你必须使用ValidateAntiForgeryToken,而且Identity框架已经内置了一个出色的哈希和盐处理机制。

请问一个问题:我们不需要Identity的默认数据库模式,对吗?我的意思是,我们将管理自己的用户验证,不需要在SQL Server或LocalDB中拥有Identity表(在Visual Studio开发时会使用)。

是的,您不需要Identity的默认模式,就像我在这个示例中所做的那样。我只是绕过了Identity的UserStore和UserManager类,但是使用了其他部分来验证用户。还要记住,您可以通过实现IUserStore接口来自定义自己的UserStore,并与Identity的UserManager集成。

非常感谢你的快速回复!是的,我们不使用Identity的持久化。问题是,当身份验证cookie过期时,我们会遇到一个错误,因为SQL Server无法响应。似乎它正在尝试针对Identity数据库验证某些内容。我们在Application_Error(在Global.asax文件中)中捕获了异常并重定向到登录页面,但问题是网站在连接到SQL Server之前会等待超时。这只会在cookie过期时发生。

看起来你的regenerateIdentityCookieAuthenticationProvider中仍然使用默认的UserStore

这种方法是可以的,但是要考虑到在用户注销之前,它不会更新声明。解决这个问题的方法会更加昂贵,因为您需要每次都要检查数据库的角色。

0