是否可以使用ASP.NET MVC创建登录系统但不使用MembershipProvider?

Lia*_*mGu 58 authentication asp.net-mvc

我有一个带有用户表的现有数据库,我们计划将数据库用于构建在ASP.NET MVC中的新系统.但是,我不确定的是我是否能够创建一个不使用内置帐户控制器或常规成员资格提供程序的登录系统,以便我们仍然可以使用现有的表结构.

所以我的问题是,这可能吗?或者甚至特别难以做到的话?

什么是最广泛接受的做事方式和最简单的做法?

Mat*_*ock 81

我有同样的要求.我有自己的用户和角色模式,并且不想迁移到asp.net成员资格模式,但我确实想使用ASP.NET MVC操作过滤器来检查授权和角色.我不得不做大量的挖掘工作才能确切地知道需要做什么,但最后它相对容易.我会救你麻烦并告诉你我做了什么.

1)我创建了一个派生自System.Web.Security.MembershipProvider的类.MembershipProvider有各种各样的身份验证相关功能的抽象方法,如忘记密码,更改密码,创建新用户等.我想要的是能够根据自己的架构进行身份验证.所以我的课程主要包含空的覆盖.我只是覆盖了ValidateUser:

public override bool ValidateUser(string username, string password)
{
    if (string.IsNullOrWhiteSpace(username) ||
        string.IsNullOrWhiteSpace(password))
      return false;

    string hash = EncryptPassword(password);
    User user = _repository.GetByUserName(username);
    if (user == null) return false;

    return user.Password == hash;
}
Run Code Online (Sandbox Code Playgroud)

2)我创建了一个派生自System.Web.Security.RoleProvider的类.再一次,我只是为了创建和更改角色而不需要的所有漏洞实现空实现.我只是覆盖了两种方法:

public override string[] GetRolesForUser(string username)
{
    User user = _repository.GetByUserName(username);
    string[] roles = new string[user.Role.Rights.Count + 1];
    roles[0] = user.Role.Description;
    int idx = 0;
    foreach (Right right in user.Role.Rights)
        roles[++idx] = right.Description;
    return roles;
}

public override bool IsUserInRole(string username, string roleName)
{
    User user = _repository.GetByUserName(username);
    if(user!=null)
        return user.IsInRole(roleName);
    else
        return false;
}
Run Code Online (Sandbox Code Playgroud)

3)然后我将这两个类插入我的web.config:

<membership defaultProvider="FirstlookMemberProvider" userIsOnlineTimeWindow="15">
  <providers>
    <clear/>
    <add name="FirstlookMemberProvider" type="FirstlookAdmin.DomainEntities.FirstlookMemberProvider, FirstlookAdmin" />
  </providers>
</membership>
<roleManager defaultProvider="FirstlookRoleProvider" enabled="true" cacheRolesInCookie="true">
  <providers>
    <clear/>
    <add name="FirstlookRoleProvider" type="FirstlookAdmin.DomainEntities.FirstlookRoleProvider, FirstlookAdmin" />
  </providers>
</roleManager>
Run Code Online (Sandbox Code Playgroud)

而已.默认授权操作筛选器将使用这些类.您仍然必须处理登录页面登录并注销.只需像往常一样使用标准表单身份验证类.

  • 我在此博客上提供了更完整的代码示例.我希望这篇文章会有所帮助:http://mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx (19认同)
  • 哦,值得指出的是,密码应该在散列之前使用nonce进行腌制. (4认同)

Cra*_*ntz 11

每当有人告诉你安全相关的东西"容易"时,他们几乎总是错的.安全性有很多微妙之处,非专家往往会错过.

特别是,没有明确处理缓存的任何形式的身份验证都是固有的.缓存操作结果时,这发生在ASP.NET中,不一定在ASP.NET MVC堆栈中.如果检查AuthorizeAttribute的源代码,您将看到它包含一些稍微棘手但有效的代码,以确保它始终运行,即使缓存了操作结果.

到目前为止,自定义ASP.NET MVC身份验证的最佳方法是编写自定义ASP.NET成员资格提供程序.我不会声称这是万无一失的,但是在这条路线中使用其他方法破坏安全实施的麻烦的方法较少.这种技术的一个重要优点是您几乎可以在任何时候替换不同的授权系统,而无需更改代码.

如果必须实现自定义MVC属性,则应该对AuthorizeAttribute进行子类型并覆盖AuthorizeCore,并仔细记录源代码中有关线程安全性的注释.


小智 10

当然可以.我为我的项目做了完全忽略会员提供者.

您需要实现自己的ActionFilter.基本上,它会在控制器动作被击中之前拦截控制.在其中,您决定是继续操作还是将用户重定向到登录页面.

对于该属性,您可以定义支持身份验证/授权模型所需的任何参数.

public class AuthorizationAttribute : ActionFilterAttribute, IActionFilter
{
   public MyRole UserRole { get; set; }

   void IActionFilter.OnActionExecuting (ActionExecutedContext filterContext)
   {
       // Decide whether to grant access to the action or redirect away
   }
}

[Authorization (UserRole = MyRole.All)]
public class UserController : Controller
{
    [Authorization (UserRole = MyRole.Admin)]
    public ActionResult Delete ()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

关于评论中表达的关注.是的,启用输出缓存会干扰授权.人们必须意识到这一点.

问题的解释:ASP.NET MVC提示#40 - 不要缓存需要授权的页面