Click here to Skip to main content
6,629,377 members and growing! (21,360 online)
Email Password   helpLost your password?
Web Development » ASP.NET » Howto     Intermediate License: The Code Project Open License (CPOL)

Using a Custom Base Class for Security and Session Management

By yordan_georgiev

Using a custom base class for security and Session management.
C# (C# 3.0), .NET (.NET 3.0, .NET 3.5), ASP.NET, Dev
Posted:21 Jun 2008
Views:12,802
Bookmarked:31 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
5 votes for this article.
Popularity: 2.45 Rating: 3.50 out of 5
1 vote, 20.0%
1

2
1 vote, 20.0%
3

4
3 votes, 60.0%
5

Introduction

One of the requirements of the project I work on is that, "the admin should be able to mark a user as inactive, so the user would not be able to access the application anymore even if he is currently logged in". First, I thought that this would not be possible, but later on, I found this graat article by Robert Boedigheimer, which suggested the use of a custom base class, which brought to me an entire new horizon on how to tackle the two most important parts of writing .NET web based applications - security and memory management.

Using the code

Derive your page from the base class. In the code-behind file, use:

public partial class MyImportantPage : CustomBasePage

Thus, your pages will have all the properties of the System.Web.UI.Page class plus those you have defined in your base class. The second advantage of this class is Session management. Let us assume that you have 1 GB of RAM on your Web server. What would happen if you retrieve a couple of datasets per page (1 MB each)? Your Session expiration time is 30 minutes and the number of on-line users is close to 600 ... Well, with those simulated numbers, with the default settings, the IIS will perform a memory cleaning and throw all the users out ...

In reality, most of the variables set as Session variables do not need to be global, but are page-specific... Somebody might argue to use ViewState for those variables - well, watch the performance after setting a dataset with a 1 MB size ... the ViewState should only be used for small variables. Another option is to use the Cache ... My experience is that the Cache is unreliable - you cannot be 100% sure what the client browser will do to your important objects stored, yet your code rules the server ...

When you would like to set a variable which is to be used globally (e.g., the variable will persist through the time of the current session of the user, even if the user leaves the current page), set the variable like so:

string StrGlobalVariable = Session [ "global.StrGlobalVariable" ];

When you would like to use a variable only in the scope of the page (e.g., the variable will be deleted once the user requests a different page), set the variable as follows:

string StrPageVariable = Session [ base.PageName + ".PageVariable" ] ;

So, here is the code (read the comments carefully):

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Generic;
using System.Text;

//SOURCE:http://aspalliance.com/63
//AUTHOR:Robert Boedigheimer
//page life cycle http://msdn.microsoft.com/en-us/library/ms178472.aspx

public class CustomBasePage : System.Web.UI.Page
{
 private string pageName;
#region Properties

    /// <summary>
    /// Each page should "know" its name
    /// </summary>
    public string PageName
    {
        get
        {
            return System.IO.Path.GetFileNameWithoutExtension (
                   System.Web.HttpContext.Current.Request.Url.AbsolutePath );
        } //eof get
        set { pageName = value; } //eof set
    } //eof property MyPageName

    #endregion //Properties


  public CustomBasePage ()
  {
  }

  override protected void OnInit ( EventArgs e )
  {
   base.OnInit ( e );
   #region Introduction
   string msg;
   string baseDir;
   string pageName;
  #endregion //Introduction


 #region Instantiation
  pageName = System.IO.Path.GetFileNameWithoutExtension (
             System.Web.HttpContext.Current.Request.Url.AbsolutePath );

//Utils.Debugger.WriteIf ( pageName + "            OnInit --- Start " );
//ucomment this to debug each page after the login
        //Utils.Debugger.DebugPage ( this.Page );

        
        if (HttpContext.Current.Session != null)
        {

            //Tested and the IsNewSession is more advanced then simply checking if 
            // a cookie is present, it does take into account a session timeout, because 
            // I tested a timeout and it did show as a new session
            if (HttpContext.Current.Session.IsNewSession)
            {
                // If it says it is a new session,
                // but an existing cookie exists, then it must 
                // have timed out (can't use the cookie
                // collection because even on first 
                // request it already contains the cookie (request and response
                // seem to share the collection)
                string szCookieHeader = Request.Headers [ "Cookie" ];
                if (( null != szCookieHeader ) &&
                ( szCookieHeader.IndexOf ( "ASP.NET_SessionId" ) >= 0 ))
                {
                    HttpContext.Current.Session [ "global.msg" ] = 
                        " No action has been performed in " + 
                        "the last 15 minutes, please login again";
                    Response.Redirect ( "~/login.aspx" );
                }
            } //eof if (HttpContext.Current.Session.IsNewSession)
        } //eof is Session is not null 



        //comm - if this is not the login page AND 
        if (Session [ "global.LOGINISOK" ] == null || 
            System.Convert.ToString ( 
            Session [ "global.LOGINISOK" ] ).Equals ( "LOGINISOK" ) == false)
        {
            Utils.Debugger.WriteIf ( Session [ "global.Domain_Name" ] + 
            " redirecting to login page !!!: \n" );
            Session [ "global.msg" ]  = 
            "Welcome to the My Application name ! Please, login first ";
            Response.Redirect ( "~/login.aspx" );

        }
        else   //comm --   
        {
            //comm - clear all session variables , 
            //but the global ones and the ones belonging to this page
    ClearAllNonGlobalSessionsButMine ();
        }
    } //eof OnInit



    /// <summary>
    /// This method relies on the convention practice that the Session keys
    /// would be named as follows:
    /// pageName.variableName - if the Session variable is page specific and 
    /// global.variableName - if the Session variable should be trully global
    /// </summary>
    private void ClearAllNonGlobalSessionsButMine ()
    {
        string fileNameNoExt = System.IO.Path.GetFileNameWithoutExtension (
                 System.Web.HttpContext.Current.Request.Url.AbsolutePath );

        for (int i = 0; i< HttpContext.Current.Session.Count; i++)
        {
            string keyValue = HttpContext.Current.Session.Keys [ i ];
            if (keyValue.Contains ( fileNameNoExt ) || keyValue.Contains ( "global" ))
            { ; }        //do nothing = preserve the value in the session 
            else
            {
              //answers the question: what session
              //variables are deleted during page change
              HttpContext.Current.Session [ HttpContext.Current.Session.Keys [ i ] ] = null;
            } //eof else if it is global or belongs to current page
        } //eof loop 

    } //eof public static void ClearAllButCurrent (string pageName )  

public void ClearAllNonGlobalSessionsAndMine ()
{
string fileNameNoExt = System.IO.Path.GetFileNameWithoutExtension (
                                System.Web.HttpContext.Current.Request.Url.AbsolutePath );

  for (int i = 0; i< HttpContext.Current.Session.Count; i++)
  {
  string keyValue = HttpContext.Current.Session.Keys [ i ];
  if (keyValue.Contains ( "global" ))
  { ; }  //do nothing = preserve the value in the session 
  else
  {
  //answers the question: what session variables are deleted during page change
  HttpContext.Current.Session [ HttpContext.Current.Session.Keys [ i ] ] = null;
} //eof else if it is global or belongs to current page
} //eof loop 

} //eof public static void ClearAllButCurrent (string pageName )  


} //eof BasePageClass

I almost noticed, you wandered what the DebugPage method is. Here it is:

using System;
using System.Text.RegularExpressions;
using System.Data;
using System.Web.UI.WebControls;

namespace Utils
    {
    /// <summary>
    /// Summary description for Utils.Debugger
    /// </summary>
    public class Debugger

public static void DebugPage ( System.Web.UI.Page page )
{

string baseDirLocal = System.Web.HttpContext.Current.Server.MapPath ( "~" );
Regex Remover = new Regex ( @"^.*(\\|\/)(.*)$",
RegexOptions.IgnoreCase | RegexOptions.Compiled );
string bareDir = Remover.Replace (  baseDirLocal , "$2" );


string strToRemoveAtEnd= System.Web.HttpContext.Current.Request.Url.AbsolutePath;
char [] charsToRemoveAtEnd = strToRemoveAtEnd.ToCharArray ();
string baseDir = System.Web.HttpContext.Current.Request.Url.AbsoluteUri;
baseDir = baseDir.TrimEnd ( charsToRemoveAtEnd );
baseDir = baseDir + "/" + bareDir + "/";



WriteIf("The basedir of the project locally is " +  
        "HttpContext.Current.Server.MapPath(\"~/\");" +
        System.Web.HttpContext.Current.Server.MapPath ( "~" ) );

WriteIf ( "The basedir of the project locally is " + 
          "AppDomain.CurrentDomain.BaseDirectory;" + 
          AppDomain.CurrentDomain.BaseDirectory);

WriteIf ( "The virtual path of this page " + 
          "( System.Web.HttpContext.Current.Request.PathInfo) is " + 
          System.Web.HttpContext.Current.Request.PathInfo ) ;

WriteIf ( "System.IO.Path.GetFileName (" + 
          " System.Web.HttpContext.Current.Request.Url.AbsolutePath ) -- " + 
          System.IO.Path.GetFileName ( 
          System.Web.HttpContext.Current.Request.Url.AbsolutePath ) );
WriteIf ( "System.Web.HttpContext.Current.Request.Url.AbsolutePath -- " + 
          System.Web.HttpContext.Current.Request.Url.AbsolutePath );
WriteIf ( "System.Web.HttpContext.Current.Request.Url.AbsoluteUri -- " + 
          System.Web.HttpContext.Current.Request.Url.AbsoluteUri );
WriteIf ( "System.Web.HttpContext.Current.Request.Url.DnsSafeHost -- " + 
          System.Web.HttpContext.Current.Request.Url.DnsSafeHost );
WriteIf ( "System.Web.HttpContext.Current.Request.Url.Fragment -- " + 
          System.Web.HttpContext.Current.Request.Url.Fragment );
WriteIf ( "System.Web.HttpContext.Current.Request.Url.Host -- " + 
          System.Web.HttpContext.Current.Request.Url.Host ) ; 
WriteIf ( "System.Web.HttpContext.Current.Request.Url.HostNameType -- " + 
          System.Web.HttpContext.Current.Request.Url.HostNameType ) ;
WriteIf ( "System.Web.HttpContext.Current.Request.Url.LocalPath -- " + 
          System.Web.HttpContext.Current.Request.Url.LocalPath ) ;
WriteIf ( "System.Web.HttpContext.Current.Request.Url.OriginalString -- " + 
          System.Web.HttpContext.Current.Request.Url.OriginalString ) ;
WriteIf ( "System.Web.HttpContext.Current.Request.Url.PathAndQuery -- " + 
          System.Web.HttpContext.Current.Request.Url.PathAndQuery ) ;
WriteIf ( "System.Web.HttpContext.Current.Request.Url.Scheme -- " + 
          System.Web.HttpContext.Current.Request.Url.Scheme ) ;
WriteIf ( "System.Web.HttpContext.Current.Request.Url.Segments.ToString () -- " + 
          System.Web.HttpContext.Current.Request.Url.Segments.ToString () );
WriteIf ( "System.Web.HttpContext.Current.Request.Url.UserInfo -- " + 
          System.Web.HttpContext.Current.Request.Url.UserInfo );
WriteIf ( "System.Web.HttpContext.Current.Request.ServerVariables[ \"HTTP_COOKIE\" ] is " + 
          System.Web.HttpContext.Current.Request.ServerVariables [ "HTTP_COOKIE" ] );

} //eof DebugPage

        public static void WriteIf ( string msg )
        {
  System.Diagnostics.Debug.WriteIf ( System.Convert.ToBoolean
    ( System.Configuration.ConfigurationSettings.AppSettings [ "Debugging" ] ) ,
  DateTime.Now.ToString ( "yyyy:MM:dd -- hh:mm:ss.fff --- " ) + msg + "\n" );
        }
} //eof class Debugger 
} //eof namespace  Utils

Points of interest

If you have carefully read the code, now you know where to put your code for implementing the requirement I presented above. If you are still having difficulties figuring out, put a comment below, and I will spare more time for writing an article about it ...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

yordan_georgiev


Member
I work in OXIT - a small IT consulting company, which has participated in the building of the most sophisticated IT Systems for several big Finnish and international companies (including Fortune 500 members) and continues to provide highly sophisticated IT Solutions to its customers.

I enjoy designing and implementing software or small scripts in different programming languages.

I am fascinated by the magic of software, which has the power to change the world.
Occupation: Web Developer
Company: Oxit Oy
Location: Finland Finland

Other popular ASP.NET articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 17 of 17 (Total in Forum: 17) (Refresh)FirstPrevNext
GeneralHow to open web page with several tabs in browser using sap.net 2.0 Pinmembergunasundari0:14 31 Oct '09  
GeneralThank You (and one small request) PinmemberforCryingOutLoud12:10 21 May '09  
GeneralRe: Thank You (and one small request) Pinmemberyordan_georgiev15:30 21 May '09  
GeneralMethod for testing for timed out session is incomplete Pinmemberccady10:55 19 Nov '08  
GeneralRe: Method for testing for timed out session is incomplete Pinmemberyordan_georgiev2:31 20 Nov '08  
Generalmultiple tabs Pinmemberdbwinger3:20 23 Jun '08  
GeneralRe: multiple tabs PinmemberMike Ellison4:07 23 Jun '08  
GeneralRe: multiple tabs Pinmemberdbwinger4:12 23 Jun '08  
GeneralRe: multiple tabs Pinmemberyordan_georgiev21:52 25 Jun '08  
GeneralRe: multiple tabs Pinmemberdbwinger3:13 26 Jun '08  
GeneralRe: multiple tabs [modified] Pinmemberyordan_georgiev8:58 23 Jun '08  
GeneralRe: multiple tabs Pinmemberstar652256920:57 24 Jun '08  
GeneralA different type of though. PinmemberRajib Ahmed7:28 22 Jun '08  
GeneralHow about an HttpModule? PinmemberMike Ellison5:56 22 Jun '08  
GeneralRe: How about an HttpModule? [modified] Pinmemberyordan_georgiev20:59 22 Jun '08  
GeneralRe: How about an HttpModule? PinmemberMike Ellison4:11 23 Jun '08  
GeneralRe: How about an HttpModule? Pinmemberyordan_georgiev21:29 23 Jun '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 21 Jun 2008
Editor: Smitha Vijayan
Copyright 2008 by yordan_georgiev
Everything else Copyright © CodeProject, 1999-2009
Web17 | Advertise on the Code Project