Просмотр исходного кода

* SessionStateModule.cs: If using cookieless sessions add an
onbegin request handler that parsers out session ids and rewrites
the path. Also redirect to a url with an embedded session id if we
are creating a new cookieless session.
* SesionInProcHandler.cs:
* SessionSQLServerHandler.cs:
* SessionStateServerHandler.cs: Use SessionId::Lookup to lookup session
ids, don't set the session id cookie anymore. That is handled by
the SessionStateModule.
* SessionId.cs: Add method for looking up session ids, add
some constants.

svn path=/trunk/mcs/; revision=20759

Jackson Harper 22 лет назад
Родитель
Сommit
db3acd1383

+ 13 - 0
mcs/class/System.Web/System.Web.SessionState/ChangeLog

@@ -1,3 +1,16 @@
+2003-12-03  Jackson Harper <[email protected]>
+
+	* SessionStateModule.cs: If using cookieless sessions add an
+	onbegin request handler that parsers out session ids and rewrites
+	the path. Also redirect to a url with an embedded session id if we
+	are creating a new cookieless session.
+	* SesionInProcHandler.cs:
+	* SessionSQLServerHandler.cs:
+	* SessionStateServerHandler.cs: Use SessionId::Lookup to lookup session
+	ids, don't set the session id cookie anymore. That is handled by
+	the SessionStateModule.
+	* SessionId.cs: Add method for looking up session ids, add some constants.
+	
 2003-11-26  Jackson Harper <[email protected]>
 
 	* SessionSQLServerHandler.cs: Fix typo in param name.

+ 16 - 4
mcs/class/System.Web/System.Web.SessionState/SessionId.cs

@@ -18,13 +18,16 @@ namespace System.Web.SessionState {
 		private static char [] allowed = { '0', '1', '2', '3', '4', '5',
 						   '6', '7', '8', '9', 'A', 'B',
 						   'C', 'D', 'E', 'F' };
+
+		internal static readonly int IdLength = 30;
+		private static readonly int half_len = 15;
 		
 		internal static string Create (RandomNumberGenerator rng)
 		{
 			if (rng == null)
 				throw new ArgumentNullException ("rng");
 			
-			byte[] key = new byte[15];
+			byte[] key = new byte [half_len];
 			
 			rng.GetBytes (key);
 			return Encode (key);
@@ -34,18 +37,27 @@ namespace System.Web.SessionState {
 		{
 			if (key == null)
 				throw new ArgumentNullException ("key");
-			if (key.Length != 15)
+			if (key.Length != half_len)
 				throw new ArgumentException ("key must be 15 bytes long.");
 
 			// Just a standard hex conversion
-			char[] res = new char [30];
-			for (int i=0; i < 15; i++) {
+			char[] res = new char [IdLength];
+			for (int i=0; i < half_len; i++) {
 				int b = key [i];
 				res [i * 2] = allowed [b >> 4];
 				res [(i * 2) + 1] = allowed [b & 0xF];
 			}
 			return new String (res);
 		}
+
+		internal static string Lookup (HttpRequest request, bool cookieless)
+		{
+			if (cookieless)
+				return (string) request.Headers [SessionStateModule.HeaderName];
+			else if (request.Cookies [SessionStateModule.CookieName] != null)
+				return request.Cookies [SessionStateModule.CookieName].Value;
+			return null;
+		}
 	}
 
 }

+ 9 - 13
mcs/class/System.Web/System.Web.SessionState/SessionInProcHandler.cs

@@ -12,7 +12,7 @@
 
 	TODO:
 	    * Remove abandoned sessions., preferably by a worker thread sleeping most of the time.
-            * Increase session security, for example by using UserAgent i hashcode.
+	    * Increase session security, for example by using UserAgent i hashcode.
 	    * Generate SessionID:s in a good (more random) way.
 */
 using System;
@@ -57,10 +57,11 @@ namespace System.Web.SessionState
 	internal class SessionInProcHandler : ISessionHandler
 	{
 		protected Hashtable _sessionTable;
-		const string COOKIE_NAME = "ASPSESSION"; // The name of the cookie.
 		// The length of a session, in minutes. After this length, it's abandoned due to idle.
 		const int SESSION_LIFETIME = 45;
 
+		private SessionConfig config;
+		
 		public void Dispose ()
 		{
 			_sessionTable = null;
@@ -68,6 +69,7 @@ namespace System.Web.SessionState
 
 		public void Init (HttpApplication context, SessionConfig config)
 		{
+			this.config = config;
 			_sessionTable = (Hashtable) AppDomain.CurrentDomain.GetData (".MonoSessionInProc");
 			if (_sessionTable == null)
 				_sessionTable = new Hashtable();
@@ -81,11 +83,12 @@ namespace System.Web.SessionState
 		public bool UpdateContext (HttpContext context, SessionStateModule module)
 		{
 			SessionContainer container = null;
-
+			string id = SessionId.Lookup (context.Request, config.CookieLess);
+			
 			//first we try to get the cookie.
 			// if we have a cookie, we look it up in the table.
-			if (context.Request.Cookies [COOKIE_NAME] != null) {
-				container = (SessionContainer) _sessionTable [context.Request.Cookies [COOKIE_NAME].Value];
+			if (id != null) {
+				container = (SessionContainer) _sessionTable [id];
 
 				// if we have a session, and it is not expired, set isNew to false and return it.
 				if (container!=null && container.SessionState!=null && !container.SessionState.IsAbandoned) {
@@ -97,8 +100,7 @@ namespace System.Web.SessionState
 					context.SetSession (container.SessionState);
 					return false; // and we're done
 				} else if(container!=null) {
-					//A empty or expired session, lets kill it.
-					_sessionTable[context.Request.Cookies[COOKIE_NAME]]=null;
+					_sessionTable.Remove (id);
 				}
 			}
 
@@ -120,12 +122,6 @@ namespace System.Web.SessionState
 			context.SetSession (container.SessionState);
 			context.Session.IsNewSession = true;
 
-
-			// sets the session cookie. We're assuming that session scope is the default mode.
-			HttpCookie cookie = new HttpCookie (COOKIE_NAME,sessionID);
-			cookie.Path = Path.GetDirectoryName (context.Request.Path);
-			context.Response.AppendCookie (cookie);
-
 			// And we're done!
 			return true;
 		}

+ 1 - 12
mcs/class/System.Web/System.Web.SessionState/SessionSQLServerHandler.cs

@@ -18,7 +18,6 @@ namespace System.Web.SessionState {
 
 	internal class SessionSQLServerHandler : ISessionHandler
 	{
-		const string CookieName = "ASPSESSION";
 		const int DefTimeout = 600;
 
 		private Type cncType = null;
@@ -75,7 +74,7 @@ namespace System.Web.SessionState {
 		public bool UpdateContext (HttpContext context, SessionStateModule module)
 		{
 			HttpSessionState session = null;
-			string id = GetId (context);
+			string id = SessionId.Lookup (context.Request, config.CookieLess);
 
 			if (id != null) {
 				session = SelectSession (id);
@@ -93,7 +92,6 @@ namespace System.Web.SessionState {
 			InsertSession (session, config.Timeout);
 			context.SetSession (session);
 			context.Session.IsNewSession = true;
-			context.Response.AppendCookie (new HttpCookie (CookieName, id));
 
 			return true;
 		}
@@ -216,15 +214,6 @@ namespace System.Web.SessionState {
 			return DateTime.Now.AddDays (1);
 		}
 
-		private string GetId (HttpContext context)
-		{
-			if (!config.CookieLess &&
-					context.Request.Cookies [CookieName] != null)
-				return context.Request.Cookies [CookieName].Value;
-
-			return null;
-		}
-
 		private byte [] ReadBytes (IDataReader reader, int index)
 		{
 			int len = (int) reader.GetBytes (reader.FieldCount-1, 0, null, 0, 0);

+ 41 - 10
mcs/class/System.Web/System.Web.SessionState/SessionStateModule.cs

@@ -3,12 +3,14 @@
 //
 // Authors:
 //	Gonzalo Paniagua Javier ([email protected])
-//      Stefan Görling ([email protected])
+//	Stefan Görling ([email protected])
+//      Jackson Harper ([email protected])
 //
 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
 // (C) 2003 Stefan Görling (http://www.gorling.se)
 
 using System.Web;
+using System.Web.Util;
 using System.Security.Cryptography;
 
 namespace System.Web.SessionState
@@ -16,6 +18,9 @@ namespace System.Web.SessionState
 	[MonoTODO]
 	public sealed class SessionStateModule : IHttpModule, IRequiresSessionState
 	{
+		internal static readonly string CookieName = "ASPSESSION";
+		internal static readonly string HeaderName = "AspFilterSessionId";
+		
 		static SessionConfig config;
 		static Type handlerType;
 		ISessionHandler handler;
@@ -27,10 +32,10 @@ namespace System.Web.SessionState
 			rng = new RNGCryptoServiceProvider ();
 		}
 
-                internal RandomNumberGenerator Rng {
-                        get { return rng; }
-                }
-                
+		internal RandomNumberGenerator Rng {
+			get { return rng; }
+		}
+		
 		public void Dispose ()
 		{
 		    if (handler!=null)
@@ -54,7 +59,10 @@ namespace System.Web.SessionState
 				if (config.Mode == SessionStateMode.InProc)
 					handlerType = typeof (SessionInProcHandler);
 			}
-				
+
+			if (config.CookieLess)
+				app.BeginRequest += new EventHandler (OnBeginRequest);
+			
 			app.AddOnAcquireRequestStateAsync (
 				new BeginEventHandler (OnBeginAcquireState),
 				new EndEventHandler (OnEndAcquireState));
@@ -68,6 +76,21 @@ namespace System.Web.SessionState
 			}
 		}
 
+		public void OnBeginRequest (object o, EventArgs args)
+		{
+			HttpApplication application = (HttpApplication) o;
+			HttpContext context = application.Context;
+			string base_path = context.Request.BaseVirtualDir;
+			string id = UrlUtils.GetSessionId (base_path);
+
+			if (id == null)
+				return;
+			
+			context.Request.SetFilePath (UrlUtils.RemoveSessionId (base_path,
+								     context.Request.FilePath));
+			context.Request.SetHeader (HeaderName, id);
+		}
+		
 		void OnReleaseRequestState (object o, EventArgs args)
 		{
 			if (handler == null)
@@ -84,13 +107,24 @@ namespace System.Web.SessionState
 
 		IAsyncResult OnBeginAcquireState (object o, EventArgs args, AsyncCallback cb, object data)
 		{
-
 			HttpApplication application = (HttpApplication) o;
 			HttpContext context = application.Context;
 
 			bool isNew = false;
 			if (handler != null)
 			    isNew = handler.UpdateContext (context, this);
+
+			if (isNew && config.CookieLess) {
+				string id = context.Session.SessionID;
+				context.Request.SetHeader (HeaderName, id);
+				context.Response.Redirect (UrlUtils.InsertSessionId (id,
+						context.Request.FilePath));
+			} else {
+				string id = context.Session.SessionID;
+				HttpCookie cookie = new HttpCookie (CookieName, id);
+				cookie.Path = UrlUtils.GetDirectory (context.Request.Path);
+				context.Response.AppendCookie (cookie);
+			}
 			
 			// In the future, we might want to move the Async stuff down to
 			// the interface level, if we're going to support other than
@@ -119,6 +153,3 @@ namespace System.Web.SessionState
 	}
 }
 
-
-
-