سؤال

كيف يمكنني إنشاء عضوية مخصصة لـ ASP.NET MVC 2 استنادًا إلى مزود عضوية ASP.NET؟

هل كانت مفيدة؟

المحلول

لقد أنشأت مشروعًا جديدًا يحتوي على مزود عضوية مخصص وتجاوز 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 عن طريق إضافة مرجع وإشارةه من الويب الخاص بي.

<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 Auithing هذه الطريقة لمعرفة الأدوار التي يتم تعيينها للمستخدم الحالي الذي تم تسجيله ويتأكد من السماح للمستخدم بالوصول إلى إجراء وحدة التحكم.

فيما يلي الخطوات التي نحتاج إلى اتخاذها:

1) إنشاء فئة مخصصة ترث فئة RoleProvider Abstract ويتجاوز طريقة 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 عبر web.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) قم بتعيين التفويض (ROLES = "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 */);
    }
}

الآن يمكننا استخدام السمة الخاصة بنا لإعادة توجيه مستخدمينا للوصول إلى العرض المرفوض:

[MyAuthorization(Roles = "Portal Manager,Content Editor", ViewName = "AccessDenied")]
public class DropboxController : Controller
{ 
    .......
}

هذا هو! سوبر المخادع!

فيما يلي بعض الروابط التي استخدمتها للحصول على كل هذه المعلومات:

مزود الدور المخصص:http://davidhayden.com/blog/dave/archive/2007/10/17/createCustomRovIderAspnetrolePermissionsSecurity.aspx

آمل أن تساعد هذه المعلومات!

نصائح أخرى

من الممكن أيضًا استخدام هذا مع كمية أقل بكثير من التعليمات البرمجية ، لست متأكدًا تمامًا مما إذا كانت هذه الطريقة آمنة ولكنها تعمل بشكل جيد مع أي قاعدة بيانات تستخدمها.

في Global.asax

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);
                }
            }
        }
    }

ما يفعل

ويبدو منطق تسجيل الدخول مثل هذا

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);
        }
    }
}

أقوم بتخزين الأدوار الموجودة في قاعدة البيانات الخاصة بي مع جدولين: الجدول: الدور الذي يحتوي على الأعمدة: ROLOID و ROLENAME والجدول: المستخدمون WICH لديه الأعمدة: userid و roleid ، وهذا يجعل من الممكن لعدة أدوار للعديد من المستخدمين ومن السهل القيام به اجعل المنطق الخاص بك لإضافة/إزالة الأدوار من المستخدمين وما إلى ذلك. يمكّنك ذلك من استخدام [Authorize (ROLES = "Super Admin")] على سبيل المثال. أتمنى أن يساعدك هذا.

تحرير: نسيت إجراء فحص كلمة المرور ولكنك فقط تضيف ما إذا كان في طريقة تسجيل الدخول يتحقق مما إذا كان اسم المستخدم وكلمة المرور يوفر

لقد استخدمت رمز المصدر لمزود مزود Nauckit.postgresql كقاعدة ، وقمت بتعديله لتناسب احتياجاتي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top