我有一个带有users表的现有数据库,我们计划将数据库用于构建在ASP.NET MVC中的新系统。但是,我不确定的是我是否能够创建一个不使用内置帐户控制器或常规成员资格提供程序的登录系统,以便我们仍然可以使用现有的表结构。
所以我的问题是,这可能吗?或者甚至特别难以做到?
最广泛接受的做事方式是什么,最简单的?
答案 0 :(得分: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;
}
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;
}
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>
就是这样。默认授权操作筛选器将使用这些类。您仍然必须处理登录页面登录并注销。只需像往常一样使用标准表单身份验证类。
答案 1 :(得分:11)
每当有人告诉你安全相关的东西“容易”时,他们几乎总是错的。安全性有很多微妙之处,非专家往往会错过。
特别是,任何形式的身份验证都不会明确地处理缓存。当缓存操作结果时,这发生在ASP.NET中,不一定在ASP.NET MVC中堆。如果检查AuthorizeAttribute的源代码,您将看到它包含一些稍微棘手但有效的代码,以确保它始终运行,即使缓存了操作结果。
The best way, by far, to customize ASP.NET MVC authentication is to write a custom ASP.NET membership provider.我不会声称这是万无一失的,但是在这条路线中使用其他方法破坏安全实施的麻烦的方法较少。这种技术的一个重要优点是几乎可以在任何时候替换不同的授权系统,而无需更改代码。
如果必须实现自定义MVC属性,则应该对AuthorizeAttribute进行子类型并覆盖AuthorizeCore,并仔细记录源代码中有关线程安全性的注释。
答案 2 :(得分: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 ()
{
}
}
关于评论中表达的关注。是的,启用输出缓存会干扰授权。人们必须意识到这一点。
问题解释:ASP.NET MVC Tip #40 - Don’t Cache Pages that Require Authorization
答案 3 :(得分:1)
您至少有两个的可能性
IHttpModule
,它将填充已登录用户的所有必要数据(包括角色),您可以使用现有的操作过滤器第二种选择也可用于常规网络表单。