Как создать пользовательский поставщик членства для ASP.NET MVC 2?
Как создать пользовательское членство для ASP.NET MVC 2 на основе ASP.NET поставщик членства?
4 ответа:
я создал новый проект, содержащий пользовательский поставщик членства и переопределил
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); } }
затем я подключил этого провайдера к моему ASP.NET проект MVC 2, добавив ссылку и указав ее из моего веб-сайта.config:
<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
метод. The ASP.NET авторизация MVC использует этот метод, чтобы узнать какие роли назначаются текущему вошедшему в систему пользователю и удостоверяются, что пользователю разрешен доступ к действию контроллера.вот шаги, которые мы должны предпринять:
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) подключите поставщика ролей к ASP.NET приложение MVC 2 через нашу сеть.config:
<system.web> ... <roleManager enabled="true" defaultProvider="MyRoleProvider"> <providers> <clear /> <add name="MyRoleProvider" applicationName="MyApp" type="MyApp.MyRoleProvider" connectionStringName="MyMembershipConnection" /> </providers> </roleManager> ... </system.web>
3) Установите авторизацию (роли="xxx,yyy") выше разыскиваемый контроллер / действие:
[Authorization(Roles = "Customer Manager,Content Editor")] public class MyController : Controller { ...... }
вот именно! Теперь это работает!
4) необязательно: установите пользовательский
Authorize
атрибут, чтобы мы могли перенаправить нежелательную роль на страницу AccessDenied:[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
я надеюсь, что эта информация поможет!
его можно использовать и с гораздо меньшим количеством кода, я не совсем уверен, если этот метод является безопасным, но очень хорошо работает с любой базой данных, которую вы используете.
в мировой.асакс
protected void Application_AuthenticateRequest(object sender, EventArgs e) { if (HttpContext.Current.User != null) { if (HttpContext.Current.User.Identity.IsAuthenticated) { if (HttpContext.Current.User.Identity is FormsIdentity) { FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity; FormsAuthenticationTicket ticket = id.Ticket; // Get the stored user-data, in this case, our roles string userData = ticket.UserData; string[] roles = userData.Split(','); HttpContext.Current.User = new GenericPrincipal(id, roles); } } } }
что это делает, так это то, что он читает роли из authCookie, который был сделан из FormsAuthenticationTicket
и логика входа выглядит так
public class dbService { private databaseDataContext db = new databaseDataContext(); public IQueryable<vwPostsInfo> AllPostsAndDetails() { return db.vwPostsInfos; } public IQueryable<role> GetUserRoles(int userID) { return (from r in db.roles join ur in db.UsersRoles on r.rolesID equals ur.rolesID where ur.userID == userID select r); } public IEnumerable<user> GetUserId(string userName) { return db.users.Where(u => u.username.ToLower() == userName.ToLower()); } public bool logOn(string username, string password) { try { var userID = GetUserId(username); var rolesIQueryable = GetUserRoles(Convert.ToInt32(userID.Select(x => x.userID).Single())); string roles = ""; foreach (var role in rolesIQueryable) { roles += role.rolesName + ","; } roles.Substring(0, roles.Length - 2); FormsAuthenticationTicket ticket = new FormsAuthenticationTicket( 1, // Ticket version username, // Username associated with ticket DateTime.Now, // Date/time issued DateTime.Now.AddMinutes(30), // Date/time to expire true, // "true" for a persistent user cookie roles, // User-data, in this case the roles FormsAuthentication.FormsCookiePath);// Path cookie valid for // Encrypt the cookie using the machine key for secure transport string hash = FormsAuthentication.Encrypt(ticket); HttpCookie cookie = new HttpCookie( FormsAuthentication.FormsCookieName, // Name of auth cookie hash); // Hashed ticket // Set the cookie's expiration time to the tickets expiration time if (ticket.IsPersistent) cookie.Expires = ticket.Expiration; // Add the cookie to the list for outgoing response HttpContext.Current.Response.Cookies.Add(cookie); return true; } catch { return (false); } } }
Я храню роли в моей базе данных с двумя таблицами: таблица: роль, которую имеет столбцы: roleID и roleName и таблица: UsersRoles у которых есть столбцы: userID и roleID, это позволяет использовать несколько ролей для нескольких пользователей, и легко сделать свою собственную логику для добавления/удаления ролей от пользователей и т. д. Это позволяет использовать [Authorize (Roles="Super Admin")] например. надеюсь, это поможет.
edit: забыл сделать проверку пароля, но вы просто добавляете if в метод входа в систему, который проверяет, проверяет ли имя пользователя и пароль, а если нет она возвращает значение false