|
using System;
using System.Diagnostics;
using System.Threading;
using System.Web;
using System.Web.SessionState;
using System.Reflection;
using System.Reflection.Emit;
namespace StateHijack
{
/// <summary>
/// Custom implementation of SessionStateModule that aggregates "standard"
/// ASP.NET System.Web.SessionState.SessionStateModule and introduces new
/// custom StateClientManager class.
/// </summary>
public class SessionStateModule: IHttpModule
{
private static Assembly _webAsm = null;
private static Type _mgrType = null;
private object _mgr = null;
private SessionStateModuleWrapper _origModuleWrapper = null;
private Type CreateStateClientManagerType()
{
AppDomain curDomain = Thread.GetDomain();
AssemblyName asmName = new AssemblyName();
asmName.Name = "StateHijack.StateClientManager";
AssemblyBuilder asmBuilder = curDomain.DefineDynamicAssembly(
asmName,
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule(
"StateClientManager",
"StateHijack.StateClientManager.dll");
StateClientManagerFactory mgrFactory = new StateClientManagerFactory();
Type retVal = mgrFactory.Create(
"StateClientManager",
modBuilder,
typeof(StateClientManagerImp),
_webAsm.GetType( "System.Web.SessionState.IStateClientManager", true) );
// You may want to save this generated assembly for
// testing (ildasm-ing and reflector-ing) purposes.
// asmBuilder.Save("StateHijack.StateClientManager.dll");
return retVal;
}
private void InitializeUnderlyingObjects()
{
if ( _webAsm == null )
{
_webAsm = Assembly.GetAssembly(
typeof(System.Web.SessionState.SessionStateModule));
// Generate our custom StateClientManager class
_mgrType = CreateStateClientManagerType();
}
if (_origModuleWrapper == null)
{
// Create an instance of the original SessionStateModule
_origModuleWrapper = new SessionStateModuleWrapper();
_origModuleWrapper.InnerObject =
new System.Web.SessionState.SessionStateModule();
// Create an instance of the newly generated StateClientManager class
_mgr = Activator.CreateInstance(_mgrType);
}
}
public void Init(HttpApplication app)
{
lock (this)
{
InitializeUnderlyingObjects();
// Mimic original SessionStateModule.Init behavior
ConfigWrapper config = new ConfigWrapper();
config.InnerObject = HttpContext.GetAppConfig("system.web/sessionState");
if (config.InnerObject == null)
{
config.Ctor();
}
InitModuleFromConfig(app, config.InnerObject, true);
// For OutOfProc and SQLServer, this call checks
// HttpRuntime.HasAspNetHostingPermission(
// AspNetHostingPermissionLevel.Medium);
if (!_origModuleWrapper.CheckTrustLevel(config.InnerObject))
{
_origModuleWrapper.s_trustLevelInsufficient = true;
}
_origModuleWrapper.s_config = config.InnerObject;
} // lock
if (_origModuleWrapper._mgr == null)
{
InitModuleFromConfig(app, _origModuleWrapper.s_config, false);
}
if (_origModuleWrapper.s_trustLevelInsufficient)
{
throw new HttpException("Session state need higher trust");
}
}
public void InitModuleFromConfig(
HttpApplication app,
object configObject,
bool configInit)
{
ConfigWrapper config = new ConfigWrapper();
config.InnerObject = configObject;
// Mimic original SessionStateModule.InitModuleFromConfig behavior
if (config._mode == SessionStateMode.Off)
{
return;
}
if (config._isCookieless)
{
// Cookieless functionality requires adding this handler
app.BeginRequest += new EventHandler( this.OnBeginRequest );
// Add session id to the path
HttpContextWrapper curContext = new HttpContextWrapper();
curContext.InnerObject = curContext.Current;
_origModuleWrapper.s_appPath =
curContext.InnerObject.Request.ApplicationPath;
if (_origModuleWrapper.s_appPath[
_origModuleWrapper.s_appPath.Length - 1] != '/')
{
_origModuleWrapper.s_appPath += "/";
}
_origModuleWrapper.s_iSessionId =
_origModuleWrapper.s_appPath.Length;
_origModuleWrapper.s_iRestOfPath =
_origModuleWrapper.s_iSessionId + 0x1a;
}
// Add event handlers
app.AddOnAcquireRequestStateAsync(
new BeginEventHandler(this.BeginAcquireState),
new EndEventHandler(this.EndAcquireState));
app.ReleaseRequestState +=(new EventHandler(this.OnReleaseState));
app.EndRequest +=(new EventHandler(this.OnEndRequest));
// Instead of analyzing config and choosing between InProc, OutOfProc, SQL etc,
// "patch" original SessionStateModule object, make _mgr point to
// our instance of StateClientManager. We could even provide wrappers
// for standard state client managers (InProc, OutOfProc, SqlServer)
// and create correspondent objects here (see that switch() statement in the
// original SessionStateModule.InitModuleFromConfig), but:
// - that would require some hacking on sessionState section handler, since
// "custom" sessionState managers are not supported in 1.1;
// - we do not have a goal to come up with a "better ASP.NET";
// - ASP.NET team has already done some part of the job in .NET 2.0
_origModuleWrapper._mgr = _mgr;
if (configInit)
{
// For the sake of consistency, call IStateClientManager.SetStateModule,
// but it does not do anything anyways, see comments within
MethodInfo setStateModuleInfo = _mgrType.GetMethod(
"SetStateModule",
BindingFlags.Instance | BindingFlags.Public );
object[] invokeParams = new object[1] { _origModuleWrapper.InnerObject };
setStateModuleInfo.Invoke( _mgr, invokeParams );
}
}
public void Dispose()
{
lock(this)
{
_mgr = null;
_origModuleWrapper = null;
}
_origModuleWrapper.InnerObject.Dispose();
}
private void OnBeginRequest(object source, EventArgs eventArgs)
{
_origModuleWrapper.OnBeginRequest( source, eventArgs );
}
private IAsyncResult BeginAcquireState(
object source, EventArgs e, AsyncCallback cb, object extraData)
{
return _origModuleWrapper.BeginAcquireState( source, e, cb, extraData );
}
private void EndAcquireState(IAsyncResult ar)
{
_origModuleWrapper.EndAcquireState( ar );
}
private void OnReleaseState(object source, EventArgs eventArgs)
{
_origModuleWrapper.OnReleaseState( source, eventArgs );
}
private void OnEndRequest(object source, EventArgs eventArgs)
{
_origModuleWrapper.OnEndRequest( source, eventArgs );
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.