Controlling AspX page access from the database

Roles and sitemaps do not always suffice for controlling access to pages. Often pages are not in the Sitemap and using roles assumes that you are doing coarse permissions or have a simple permission structure.

 

The class below allows a list of allowed pages to be cached in a user’s Session and then a user’s permission may be determined from this list. The PageList should be set during authorization (i.e. post login) and removed on logout. Using a session object means you avoid database hits and thus can scale better (you can web-farm the load).

 

/// <summary>
/// Utility class that may be used to determine if a user has permission to a specific page.
/// </summary>
public static class Page
{
    /// <summary>
    /// The list of pages that the user may access. Only the pages starting "~" 
    /// are filtered.
    /// </summary>
    public static List<String> PageList
    {
        get
        {

            if (System.Web.HttpContext.Current != null)
            {
                return (List < String >) System.Web.HttpContext.Current.Session["_PagePermissions_"];
            };
            return null;
        }
        set
        {
            List < String >data = value;
            if (data != null)
            {
                for (int i = 0; i < data.Count; i++)
                {
                    data[i] = data[i].ToLower();
                }
            }
            System.Web.HttpContext.Current.Session["_PagePermissions_"] = data;
        }
    }

    /// <summary>
    /// May the current Session user access this URL. If there is no List(Null), then ALL pages
    /// are assumed accessible (because Unauthorized or Login pages would be denied access).
    /// An empty list results in all being denied
    /// </summary>
    /// <param name="relativeUrl">A Relative URL starting with ~</param>
    /// <returns>true if allowed or the relative url does not start with a ~ or there is no list</returns>
public static bool HasAccess(string relativeUrl)
{
    char[] sep = { '?' };
    var data=relativeUrl.ToLower();
    if (relativeUrl.StartsWith("~") && PageList !=null )
    {
        // We need to split off parameters i.e. default.aspx?id=434
        var parts = relativeUrl.Split(sep, StringSplitOptions.RemoveEmptyEntries);
        foreach (var item in PageList)
        {
            if (String.Compare(item, parts[0]) == 0)
            {
                return true;
            }
        }
        return false;
    }
    else
    {
        return true;
    }
}

    /// <summary>
    /// May the current Session user access this URL
    /// </summary>
    /// <param name="relativeUrl">An object with a "NavigateUrl" property starting with ~</param>
    /// <returns>true if allowed or the relative url does not start with a ~</returns>
    public static bool HasAccess(object hyperlink)
    {
        return HasAccess(hyperlink.GetProperty("NavigateUrl"));
    }
}

The last function does a little magic, because it allows you to pass in any control with a NavigateUrl property to be checked. The code for GetProperty() is shown below. It’s can be a very helpful extensions.

 

/// <summary>
///  Returns the specicfic property from the object
/// </summary>
/// <param name="dataItem">An object with properties</param>
/// <param name="field">Name of property</param>
/// <param name="defaultvalue">Value to use if missing</param>
/// <returns>the value as a string, or a null if not found</returns>
public static string GetProperty(this object dataItem, string field, string defaultvalue)
{            
    if (String.IsNullOrEmpty(field)) return defaultvalue ?? null;
    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(dataItem);
    if (props.Count > 0)
    {
        if (props[field] !=null &&  null != props[field].GetValue(dataItem))
        {
            return props[field].GetValue(dataItem).ToString();
        }
    }
    return null;
}

/// <summary>
///  Returns the specicfic property from the object
/// </summary>
/// <param name="dataItem">An object with properties</param>
/// <param name="field">Name of property</param>        
/// <returns>the value as a string, or a null if not found</returns>
public static string GetProperty(this object dataItem, string field)
{
    return GetProperty(dataItem, field,null);
}

This allows you to check a control during page load and hide items that they cannot go to. It also allows you to check if they can access the current page.

Comments

Popular posts from this blog

Simple WP7 Mango App for Background Tasks, Toast, and Tiles: Code Explanation

Yet once more into the breech (of altered programming logic)

Error : /ScriptResource.axd : Invalid viewstate.