Larry Steinle

June 28, 2014

Web Information

Filed under: C,Security,VS.Net,Web — Larry Steinle @ 1:06 am
Tags: , ,

An ASP.Net Page provides simple, convenient access to HTTP Context data like Request, Response, Server, QueryString and Cookies to name a few. While re-factoring code to improve reuse often I find a need to move code from the web page and into a reusable class. To provide a consistent coding style for both web pages and front-end library classes I use a Web Information facade class.

Web Information Overview

The WebInfo class provides consistent access to the following information:

  • Detect when running in a web application or a non-web worker thread.
  • Detect when the client is using a Safari browser.
  • Get consistent formatting for the absolute path (both root sites and sub-sites end with a forward-slash).
  • Detect when a user is assigned and authenticated.
  • Manage web page response status code.
  • Detect when Forms Authentication Mode is enabled.
  • Detect when Windows Authentication Mode is supported.
  • Detect when Windows Authentication Mode is enabled.
  • Consistent access to standard HTTP Context objects:
    • Request
    • Response
    • Server
    • Cookies
    • QueryString
    • ServerVariables
    • Session

For this class to work you will need:

Web Information Class

using System;
using System.Collections.Specialized;
using System.Security.Principal;
using System.Web;
using System.Web.Configuration;

/// <summary>
/// HTTP-specific information about an individual HTTP request.
/// </summary>
public class WebInfo
{
    #region "General HTTP Context Information"
    /// <summary>
    /// Get a value that indicates when the system is running in windows context or thread context.
    /// </summary>
    public static bool InWebContext
    {
        get { return HttpContext.Current != null; }
    }

    /// <summary>
    /// Gets the System.Web.HttpRequest object for the current HTTP request.
    /// </summary>
    public static HttpRequest Request
    {
        get { return InWebContext ? HttpContext.Current.Request : null; }
    }

    /// <summary>
    /// Gets the System.Web.HttpResponse object for the current HTTP response.
    /// </summary>
    public static HttpResponse Response
    {
        get { return InWebContext ? HttpContext.Current.Response : null; }
    }

    /// <summary>
    /// Gets the System.Web.HttpServerUtility object that
    /// provides methods used in processing Web requests.
    /// </summary>
    public static HttpServerUtility Server
    {
        get { return InWebContext ? HttpContext.Current.Server : null; }
    }
    #endregion

    #region "Site MetaData Collections"
    /// <summary>
    /// Gets a collection of cookies sent by the client.
    /// </summary>
    public static System.Web.HttpCookieCollection Cookies
    {
        get { return InWebContext ? Request.Cookies : null; }
    }

    /// <summary>
    /// Gets the collection of HTTP query string variables.
    /// </summary>
    public static NameValueCollection QueryString
    {
        get { return InWebContext ? Request.QueryString : new NameValueCollection(); }
    }

    /// <summary>
    /// Gets a collection of Web server variables.
    /// </summary>
    public static NameValueCollection ServerVariables
    {
        get { return InWebContext ? Request.ServerVariables : new NameValueCollection(); }
    }

    /// <summary>
    /// Gets the System.Web.SessionState.HttpSessionState 
    /// object for the current HTTP request.
    /// </summary>
    public static System.Web.SessionState.HttpSessionState Session
    {
        get { return InWebContext ? HttpContext.Current.Session : null; }
    }
    #endregion

    #region "Site MetaData Details"
    /// <summary>
    /// Get a value that indicates when the client browser is Safari.
    /// </summary>
    public static bool IsSafariBrowser
    {
        get { return Request.Browser.Browser.ToLower().StartsWith("safari"); }
    }

    /// <summary>
    /// Get the root path for the web application ending with a forward slash.
    /// </summary>
    public static string ApplicationAbsolutePath
    {
        get
        {
            var path = VirtualPathUtility.ToAbsolute(Request.ApplicationPath);
            if (!path.EndsWith("/")) path += "/";
            return VirtualPathUtility.ToAbsolute(path);
        }
    }
    #endregion

    #region "Security Information"
    /// <summary>
    /// Get or set user context.
    /// </summary>
    public static IPrincipal User
    {
        get { return InWebContext ? HttpContext.Current.User : System.Threading.Thread.CurrentPrincipal; }
        set
        {
            if (InWebContext) HttpContext.Current.User = value;
            System.Threading.Thread.CurrentPrincipal = value;
        }
    }

    /// <summary>
    /// Get a boolean value that indicates when a User 
    /// (Authenticated or Unauthenticated) has been defined.
    /// </summary>
    public static bool InSecurityContext
    {
        get { return User != null && User.Identity != null; }
    }

    /// <summary>
    /// Get the name of the original user before it is mapped to a user account.
    /// </summary>
    /// <remarks>
    /// The only time this value differs from UserName is when an authentication filter is applied.
    /// To see the authorized, mapped account refer to the UserName property.
    /// </remarks>
    public static string LogonUser
    {
        get { return WebInfo.ServerVariables["LOGON_USER"]; }
    }

    /// <summary>
    /// Get the user name for the current security context.
    /// </summary>
    /// <remarks>
    /// To see the mapped user name refer to LogonUser.
    /// The only time this value differs from LogonUser is when an authentication filter is applied.
    /// </remarks>
    public static string UserName
    {
        get { return InSecurityContext ? User.Identity.Name : string.Empty; }
    }

    /// <summary>
    /// Get a boolean value that indicates when a user has been authenticated.
    /// </summary>
    public static bool IsAuthenticated
    {
        get { return InSecurityContext && User.Identity.IsAuthenticated; }
    }

    /// <summary>
    /// Get or set the response status code.
    /// </summary>
    public static Int32 ResponseStatusCode
    {
        get { return InWebContext ? Response.StatusCode : 0; }
        set { if (InWebContext) Response.StatusCode = value; }
    }

    /// <summary>
    /// Indicates when a 401 challenge is being returned to the client for Windows 
    /// Authentication mode.
    /// </summary>
    /// <remarks>
    /// This error is thrown when IIS is configured to support Windows authentication 
    /// and Anonymous authentication has been disabled.
    /// </remarks>
    public static bool IsWindowsChallenge
    {
        get { return ResponseStatusCode == 401; }
    }
    #endregion

    #region "IIS Security Mode Configuration"
    /// <summary>
    /// Get a value that indicates when Windows Authentication is supported.
    /// </summary>
    /// <remarks>
    /// Not all browsers support NTLM (i.e. Safari for Windows) and NTLM / Negotiate
    /// is only supported on internal networks; not external internet.
    /// </remarks>
    public static bool IsWindowsModeSupported
    {
        get { return !IsSafariBrowser && NetInfo.IsInternalAddress; }
    }

    /// <summary>
    /// Get a value that indicates when Windows Mode is enabled.
    /// </summary>
    /// <remarks>
    /// This method requires a reference to System.DirectoryServices.dll.
    /// </remarks>
    public static bool IsWindowsModeEnabled
    {
        get
        {
            //Check Web.config to see if Windows Authentication is enabled
            var config = WebConfigurationManager.OpenWebConfiguration("~");
            var configSection = (SystemWebSectionGroup)config.GetSectionGroup("system.web");
            var auth = configSection.Authentication;
            if (auth.Mode == AuthenticationMode.Windows) return true;

            //Windows Authentication may be enabled even when Web.config is set to another mode.
            //Verify with IIS to make sure Windows Authentication is disabled.
            string iisPath = "IIS://localhost/W3SVC/1/Root" + ApplicationAbsolutePath;
            if (iisPath.EndsWith("/")) iisPath = iisPath.Substring(0, iisPath.Length - 1);
            if (System.DirectoryServices.DirectoryEntry.Exists(iisPath))
                using (var webApp = new System.DirectoryServices.DirectoryEntry(iisPath))
                    return System.Convert.ToBoolean(webApp.Properties["AuthNTLM"].Value);

            return false;
        }
    }

    /// <summary>
    /// Get a value that indicates when Forms Mode is enabled.
    /// </summary>
    public static bool IsFormsModeEnabled
    {
        get
        {
            var config = WebConfigurationManager.OpenWebConfiguration("~");
            var configSection = (SystemWebSectionGroup)config.GetSectionGroup("system.web");
            var auth = configSection.Authentication;
            return auth.Mode == AuthenticationMode.Forms;
        }
    }
    #endregion
}
Advertisement

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: