如何基于ASP.NET成员资格提供程序为ASP.NET MVC 2创建自定义成员资格?
我创建了一个包含自定义成员资格提供程序的新项目,并覆盖ValidateUser了MembershipProvider抽象类中的方法:
ValidateUser
MembershipProvider
public class MyMembershipProvider : MembershipProvider { public override bool ValidateUser(string username, string password) { // this is where you should validate your user credentials against your database. // I've made an extra class so i can send more parameters // (in this case it's the CurrentTerritoryID parameter which I used as // one of the MyMembershipProvider class properties). var oUserProvider = new MyUserProvider(); return oUserProvider.ValidateUser(username,password,CurrentTerritoryID); } }
然后,通过添加引用并将其从我的web.config中指出,将该提供程序连接到我的ASP.NET MVC 2项目:
<membership defaultProvider="MyMembershipProvider"> <providers> <clear /> <add name="MyMembershipProvider" applicationName="MyApp" Description="My Membership Provider" passwordFormat="Clear" connectionStringName="MyMembershipConnection" type="MyApp.MyMembershipProvider" /> </providers> </membership>
我确实需要创建一个继承RoleProvider抽象类并重写该GetRolesForUser方法的自定义类。ASP.NET MVC授权使用该方法找出将哪些角色分配给当前登录的用户,并确保允许该用户访问控制器操作。
RoleProvider
GetRolesForUser
这是我们需要采取的步骤:
1)创建一个自定义类,该类继承RoleProvider抽象类并覆盖GetRolesForUser方法:
public override string[] GetRolesForUser(string username) { SpHelper db = new SpHelper(); DataTable roleNames = null; try { // get roles for this user from DB... roleNames = db.ExecuteDataset(ConnectionManager.ConStr, "sp_GetUserRoles", new MySqlParameter("_userName", username)).Tables[0]; } catch (Exception ex) { throw ex; } string[] roles = new string[roleNames.Rows.Count]; int counter = 0; foreach (DataRow row in roleNames.Rows) { roles[counter] = row["Role_Name"].ToString(); counter++; } return roles; }
2)通过我们的web.config将角色提供程序与ASP.NET MVC 2应用程序连接:
<system.web> ... <roleManager enabled="true" defaultProvider="MyRoleProvider"> <providers> <clear /> <add name="MyRoleProvider" applicationName="MyApp" type="MyApp.MyRoleProvider" connectionStringName="MyMembershipConnection" /> </providers> </roleManager> ... </system.web>
3)在所需的控制器/操作上方设置Authorize(Roles =“ xxx,yyy”):
[Authorization(Roles = "Customer Manager,Content Editor")] public class MyController : Controller { ...... }
而已!现在可以了!
4)可选:设置自定义Authorize属性,以便我们可以将不需要的角色重定向到AccessDenied页面:
Authorize
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] public class MyAuthorizationAttribute : AuthorizeAttribute { /// <summary> /// The name of the master page or view to use when rendering the view on authorization failure. Default /// is null, indicating to use the master page of the specified view. /// </summary> public virtual string MasterName { get; set; } /// <summary> /// The name of the view to render on authorization failure. Default is "Error". /// </summary> public virtual string ViewName { get; set; } public MyAuthorizationAttribute () : base() { this.ViewName = "Error"; } protected void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) { validationStatus = OnCacheAuthorization(new HttpContextWrapper(context)); } public override void OnAuthorization(AuthorizationContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } if (AuthorizeCore(filterContext.HttpContext)) { SetCachePolicy(filterContext); } else if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { // auth failed, redirect to login page filterContext.Result = new HttpUnauthorizedResult(); } else if (filterContext.HttpContext.User.IsInRole("SuperUser")) { // is authenticated and is in the SuperUser role SetCachePolicy(filterContext); } else { ViewDataDictionary viewData = new ViewDataDictionary(); viewData.Add("Message", "You do not have sufficient privileges for this operation."); filterContext.Result = new ViewResult { MasterName = this.MasterName, ViewName = this.ViewName, ViewData = viewData }; } } protected void SetCachePolicy(AuthorizationContext filterContext) { // ** IMPORTANT ** // Since we're performing authorization at the action level, the authorization code runs // after the output caching module. In the worst case this could allow an authorized user // to cause the page to be cached, then an unauthorized user would later be served the // cached page. We work around this by telling proxies not to cache the sensitive page, // then we hook our custom authorization code into the caching mechanism so that we have // the final say on whether a page should be served from the cache. HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache; cachePolicy.SetProxyMaxAge(new TimeSpan(0)); cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */); } }
现在,我们可以使用自己的made属性将用户重定向到拒绝访问的视图:
[MyAuthorization(Roles = "Portal Manager,Content Editor", ViewName = "AccessDenied")] public class DropboxController : Controller { ....... }
而已!超级傻瓜!
这是我用来获取所有这些信息的一些链接:
自定义角色提供程序:http : //davidhayden.com/blog/dave/archive/2007/10/17/CreateCustomRoleProviderASPNETRolePermissionsSecurity.aspx
希望此信息对您有所帮助!