2
0

SessionStateModule.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. //
  2. // System.Web.SessionState.SesionStateModule
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. // Stefan Görling ([email protected])
  7. // Jackson Harper ([email protected])
  8. //
  9. // Copyright (C) 2002-2006 Novell, Inc (http://www.novell.com)
  10. // (C) 2003 Stefan Görling (http://www.gorling.se)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. #if !NET_2_0
  32. using System.ComponentModel;
  33. using System.Web.Configuration;
  34. using System.Web.Caching;
  35. using System.Web.Util;
  36. using System.Security.Cryptography;
  37. using System.Security.Permissions;
  38. namespace System.Web.SessionState
  39. {
  40. // CAS - no InheritanceDemand here as the class is sealed
  41. [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
  42. public sealed class SessionStateModule : IHttpModule
  43. {
  44. internal const string CookieName = "ASPSESSION";
  45. internal const string HeaderName = "AspFilterSessionId";
  46. static readonly object locker = new object ();
  47. static readonly object startEvent = new object ();
  48. static readonly object endEvent = new object ();
  49. EventHandlerList events = new EventHandlerList ();
  50. public event EventHandler Start {
  51. add { events.AddHandler (startEvent, value); }
  52. remove { events.RemoveHandler (startEvent, value); }
  53. }
  54. // This event is public, but only Session_[On]End in global.asax will be invoked if present.
  55. public event EventHandler End {
  56. add { events.AddHandler (endEvent, value); }
  57. remove { events.RemoveHandler (endEvent, value); }
  58. }
  59. #if TARGET_J2EE
  60. static private SessionConfig config {
  61. get {
  62. return (SessionConfig)AppDomain.CurrentDomain.GetData("SessionStateModule.config");
  63. }
  64. set {
  65. AppDomain.CurrentDomain.SetData("SessionStateModule.config", value);
  66. }
  67. }
  68. static private Type handlerType {
  69. get {
  70. return (Type)AppDomain.CurrentDomain.GetData("SessionStateModule.handlerType");
  71. }
  72. set {
  73. AppDomain.CurrentDomain.SetData("SessionStateModule.handlerType", value);
  74. }
  75. }
  76. #else
  77. static SessionConfig config;
  78. static Type handlerType;
  79. #endif
  80. ISessionHandler handler;
  81. bool sessionForStaticFiles;
  82. static RandomNumberGenerator rng = RandomNumberGenerator.Create ();
  83. [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)]
  84. public SessionStateModule ()
  85. {
  86. }
  87. internal RandomNumberGenerator Rng {
  88. get { return rng; }
  89. }
  90. public void Dispose ()
  91. {
  92. if (handler!=null)
  93. handler.Dispose();
  94. }
  95. SessionConfig GetConfig ()
  96. {
  97. lock (locker) {
  98. if (config != null)
  99. return config;
  100. config = (SessionConfig) HttpContext.GetAppConfig ("system.web/sessionState");
  101. if (config == null)
  102. config = new SessionConfig (null);
  103. #if TARGET_J2EE
  104. if (config.Mode == SessionStateMode.SQLServer || config.Mode == SessionStateMode.StateServer)
  105. throw new NotImplementedException("You must use web.xml to specify session state handling");
  106. #else
  107. if (config.Mode == SessionStateMode.StateServer)
  108. handlerType = typeof (SessionStateServerHandler);
  109. if (config.Mode == SessionStateMode.SQLServer)
  110. handlerType = typeof (SessionSQLServerHandler);
  111. #endif
  112. if (config.Mode == SessionStateMode.InProc)
  113. handlerType = typeof (SessionInProcHandler);
  114. return config;
  115. }
  116. }
  117. [EnvironmentPermission (SecurityAction.Assert, Read = "MONO_XSP_STATIC_SESSION")]
  118. public void Init (HttpApplication app)
  119. {
  120. sessionForStaticFiles = (Environment.GetEnvironmentVariable ("MONO_XSP_STATIC_SESSION") != null);
  121. SessionConfig cfg = GetConfig ();
  122. if (handlerType == null)
  123. return;
  124. if (cfg.CookieLess)
  125. app.BeginRequest += new EventHandler (OnBeginRequest);
  126. app.AcquireRequestState += new EventHandler (OnAcquireState);
  127. app.ReleaseRequestState += new EventHandler (OnReleaseRequestState);
  128. app.EndRequest += new EventHandler (OnEndRequest);
  129. if (handlerType != null && handler == null) {
  130. handler = (ISessionHandler) Activator.CreateInstance (handlerType);
  131. handler.Init (this, app, cfg); //initialize
  132. }
  133. }
  134. void OnBeginRequest (object o, EventArgs args)
  135. {
  136. HttpApplication application = (HttpApplication) o;
  137. HttpContext context = application.Context;
  138. string base_path = context.Request.BaseVirtualDir;
  139. string id = UrlUtils.GetSessionId (base_path);
  140. if (id == null)
  141. return;
  142. string new_path = UrlUtils.RemoveSessionId (base_path, context.Request.FilePath);
  143. context.Request.SetFilePath (new_path);
  144. context.Request.SetHeader (HeaderName, id);
  145. context.Response.SetAppPathModifier (id);
  146. }
  147. void OnReleaseRequestState (object o, EventArgs args)
  148. {
  149. if (handler == null)
  150. return;
  151. HttpApplication application = (HttpApplication) o;
  152. HttpContext context = application.Context;
  153. handler.UpdateHandler (context, this);
  154. }
  155. void OnEndRequest (object o, EventArgs args)
  156. {
  157. }
  158. void OnAcquireState (object o, EventArgs args)
  159. {
  160. HttpApplication application = (HttpApplication) o;
  161. HttpContext context = application.Context;
  162. bool required = (context.Handler is IRequiresSessionState);
  163. // This is a hack. Sites that use Session in global.asax event handling code
  164. // are not supposed to get a Session object for static files, but seems that
  165. // IIS handles those files before getting there and thus they are served without
  166. // error.
  167. // As a workaround, setting MONO_XSP_STATIC_SESSION variable make this work
  168. // on mono, but you lose performance when serving static files.
  169. if (sessionForStaticFiles && context.Handler is StaticFileHandler)
  170. required = true;
  171. // hack end
  172. bool read_only = (context.Handler is IReadOnlySessionState);
  173. bool isNew = false;
  174. HttpSessionState session = null;
  175. if (handler != null)
  176. session = handler.UpdateContext (context, this, required, read_only, ref isNew);
  177. if (session != null) {
  178. if (isNew)
  179. session.SetNewSession (true);
  180. if (read_only)
  181. session = session.Clone ();
  182. context.SetSession (session);
  183. HttpRequest request = context.Request;
  184. HttpResponse response = context.Response;
  185. string id = context.Session.SessionID;
  186. if (isNew && config.CookieLess) {
  187. request.SetHeader (HeaderName, id);
  188. UriBuilder newUri = new UriBuilder (request.Url);
  189. newUri.Path = UrlUtils.InsertSessionId (id, request.FilePath);
  190. response.Redirect (newUri.Uri.PathAndQuery);
  191. } else if (isNew) {
  192. HttpCookie cookie = new HttpCookie (CookieName, id);
  193. cookie.Path = request.ApplicationPath;
  194. context.Response.AppendCookie (cookie);
  195. }
  196. if (isNew) {
  197. OnSessionStart ();
  198. HttpSessionState hss = application.Session;
  199. if (hss != null)
  200. handler.Touch (hss.SessionID, hss.Timeout);
  201. }
  202. }
  203. }
  204. void OnSessionStart ()
  205. {
  206. EventHandler eh = events [startEvent] as EventHandler;
  207. if (eh != null)
  208. eh (this, EventArgs.Empty);
  209. }
  210. internal void OnSessionRemoved (string key, object value, CacheItemRemovedReason reason)
  211. {
  212. SessionConfig cfg = GetConfig ();
  213. // Only invoked for InProc (see msdn2 docs on SessionStateModule.End)
  214. if (cfg.Mode == SessionStateMode.InProc)
  215. HttpApplicationFactory.InvokeSessionEnd (value);
  216. }
  217. }
  218. }
  219. #endif