Programing

ASP.NET MVC 2 용 사용자 지정 멤버 자격 공급자는 어떻게 만듭니 까?

lottogame 2020. 12. 11. 07:38
반응형

ASP.NET MVC 2 용 사용자 지정 멤버 자격 공급자는 어떻게 만듭니 까?


ASP.NET 멤버 자격 공급자를 기반으로 ASP.NET MVC 2에 대한 사용자 지정 멤버 자격을 만들려면 어떻게합니까?


사용자 지정 멤버 자격 공급자를 포함하는 새 프로젝트를 만들고 추상 클래스 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 권한 부여는이 방법을 사용하여 현재 로그온 한 사용자에게 할당 된 역할을 확인하고 사용자가 컨트롤러 작업에 액세스 할 수 있는지 확인합니다.

우리가 취해야 할 단계는 다음과 같습니다.

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) 원하는 Controller / Action 위에 Authorize (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/CreateCustomRoleProviderASPNETRolePermissionsSecurity.aspx

이 정보가 도움이 되었기를 바랍니다.


This worked for me http://mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx


Its also possible to use this with a much smaller amount of code, i'm not entirely sure if this method is as safe but works very well with any database you use.

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

what this does is that it reads the roles from the authCookie which was made from FormsAuthenticationTicket

and the logon logic looks like this

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

i store the roles in my database with two tables: table: Role which has the columns: roleID and roleName and the table: UsersRoles wich has the columns: userID and roleID, this makes it possible for multiple roles for several users and it's easy to make your own logic to add/remove roles from users and so forth. This enables you to use [Authorize(Roles="Super Admin")] for instance. hope this helps.

edit: forgot to make the password check but you just add an if in the logOn method which checks if the username and password provided checks up and if not it returns false


I used the NauckIt.PostgreSQL provider's source code as a base, and modified it to suit my needs.

참고URL : https://stackoverflow.com/questions/2771094/how-do-i-create-a-custom-membership-provider-for-asp-net-mvc-2

반응형