Friday, April 13, 2012

ASP.NET Role Based Security

ASP.NET Role Based Security: The Basics

Authentication and authorization is the two basic part of the user-end security in asp.net web applications. After to successful authentication of a user, authorization takes the place according to which the authenticated user are allowed to access to the corresponding resources in the web application.
Role based security is very basic requirements in the current trend of web applications. Mostly there are two roles involved, which are registered user and the admin users. However in a web application a user can have multiple roles which can be authorized on page and page control level. Today we'll check a basic sample which includes page based authorizations for specific roles.
To implement the basic role based security, there are three points to be considered. In this example we are considering two different roles "member" and "admin". There are two separate folders named "member", which can be accessed by any logged in user, including admin users and "admin", where only the user who contains the "admin" role can access the child resources (page, images etc).
1. Defining the authorization regions in web.config
The following xml tags are required to be added under the "configuration" node of the web.config.
Defining security authorization for "member" users
  <location path="member">
    <system.web>
      <authorization>
        <deny users="?"/>
      authorization>
    system.web>
  location>
Defining security authorization for "admin" users
  <location path="admin">
    <system.web>
      <authorization>
        <allow roles="admin"/>
        <deny users="*"/>
      authorization>
    system.web>
  location>
2. Authenticating the user
After the successful authentication, the following codes are required to establish the form based authentication for the corresponding user.
//Authenticating the user Identity. 
System.Web.Security.FormsAuthentication.RedirectFromLoginPage
("member1", this.CheckBox1.Checked);
3. Implementing the role based security
The "Application_AuthenticateRequest" event which was defined in the "Global.asax" file, will include the appropriate codes regarding the role info of the logged in user, which will be accesses each time for any web request in this web application. This can be done in either "cache" or "cookie" mechanism.
Cache based mechanism
    protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
        if (HttpContext.Current.User != null)
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                if (HttpContext.Current.User.Identity.AuthenticationType != "Forms")
                    throw new Exception("Only forms authentication is supported, not " +
                        HttpContext.Current.User.Identity.AuthenticationType);
                System.Security.Principal.IIdentity userId = HttpContext.Current.User.Identity;
                //if role info is already NOT loaded into cache, put the role info in cache
                if (System.Web.HttpContext.Current.Cache[userId.Name] == null)
                {
                    string[] roles;
                   
                    if (userId.Name == "admin1")
                        roles = new string[1] { "admin" };//this info will be generally collected from database
                    else if (userId.Name == "member1")
                        roles = new string[1] { "member" };//this info will be generally collected from database
                    else
                        roles = new string[1] { "public" };//this info will be generally collected from database                  
                   
                    //1 hour sliding expiring time. Adding the roles in chache. This will be used in Application_AuthenticateRequest event located in Global.ascx.cs file to attach user Principal object.
                    System.Web.HttpContext.Current.Cache.Add(userId.Name, roles, null, DateTime.MaxValue, TimeSpan.FromHours(1), System.Web.Caching.CacheItemPriority.BelowNormal, null);
                }
               
                //now assign the user role in the current security context
                HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(userId, (string[])System.Web.HttpContext.Current.Cache[userId.Name]);
            }
        }
    }
Cookie based mechanism 
 
    protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
        if (HttpContext.Current.User != null)
        {
            if (Request.IsAuthenticated == true)
            {
                if (HttpContext.Current.User.Identity.AuthenticationType != "Forms")
                    throw new Exception("Only forms authentication is supported, not " +
                        HttpContext.Current.User.Identity.AuthenticationType);
                //Create/Retrieve cookie and initizalyze the role info in the current security context
                string userInformation = String.Empty;//where the cookie info will be placed
                string[] roles;//where the user role will be placed
                // Create the roles cookie if it doesn't exist yet for this session.
                if ((Request.Cookies["cnstUserRole"] == null) || (Request.Cookies["cnstUserRole"].Value == ""))
                {
                    if (HttpContext.Current.User.Identity.Name == "admin1")
                        roles = new string[1] { "admin" };//this info will be generally collected from database
                    else if (HttpContext.Current.User.Identity.Name == "member1")
                        roles = new string[1] { "member" };//this info will be generally collected from database
                    else
                        roles = new string[1] { "public" };//this info will be generally collected from database                   
                    // Create a string to persist the role and user id
                    userInformation = roles[0] + ";" + Context.User.Identity.Name;
                    // Create a cookie authentication ticket.
                    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                        1,                              // version
                        User.Identity.Name,             // user name
                        DateTime.Now,                   // issue time
                        DateTime.Now.AddHours(1),       // expires every hour
                        false,                          // don't persist cookie
                        userInformation
                        );
                    // Encrypt the ticket
                    String cookieStr = FormsAuthentication.Encrypt(ticket);
                    // Send the cookie to the client
                    Response.Cookies["cnstUserRole"].Value = cookieStr;
                    Response.Cookies["cnstUserRole"].Path = "/";
                    Response.Cookies["cnstUserRole"].Expires = DateTime.Now.AddMinutes(1);
                }//if role cookie not found in local pc
                else//we are getting the role info from cookie
                {
                    // Get roles from roles cookie
                    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Context.Request.Cookies["cnstUserRole"].Value);
                    userInformation = ticket.UserData;
                    //info[0] contains the single role and info[1] contains the user name
                    string[] cookieInfo = userInformation.Split(new char[] { ';' });
                    roles = new string[1] { cookieInfo[0] };
                }
                //now assign the user role in the current security context
                Context.User = new System.Security.Principal.GenericPrincipal(Context.User.Identity, roles);
            }//if (Request.IsAuthenticated == true)
        }
    }

No comments:

Post a Comment