Best practicesfast, scalable, and secure session state management for your web applicationsmichael volodarsky
Parts of this article are based on a prerelease version of ASP. NET 2.0. Those sections are subject to change.
This article discusses:
- ASP. NET 2.0 session state architecture
- Improving State management performance and scalability
- Addressing session state issues in Web farms
- Securing your state management infrastructure
|
This article uses the following technologies:
ASP. NET |
Contentshow session State works
Improving Performance
Disabling session state
Switching Network/storage overhead
Optimizing serialization
In-process Optimizations
Improving scalability
ASP. NET 2.0 session state partitioning
Securing session state
Applying ing for security
Conclusion
Due to the stateless nature of the HTTP protocol, web applications have always shouldered the burden of user State management. Fortunately, ASP. NET provides a number of ways to maintain user State, the most powerful
Of which is session state. this feature provides a convenient programmatic interface for associating arbitrary application state with a user session, and takes care of back-end state storage and client session management for the application. this article takes
An in-depth look at designing and deploying high-performance, scalable, secure session solutions, and presents best practices for both existing and new ASP. net session state Features straight from the ASP. NET feature team.
How session state worksasp. net session State lets you associate a server-side string or object dictionary containing State data with a special HTTP client session. A session is defined as a series of requests issued by the same client within a certain
Period of time, and is managed by associating a session ID with each unique client. the ID is supplied by the client on each request, either in a cookie or as a special fragment of the request URL. the session data is stored on the server side in one of
Supported session state stores, which include in-process memory, SQL Server database, and the ASP. net state Server service. the latter two modes enable session state to be shared among multiple Web servers on a Web farm and
Do not require server affinity (that is, they don't require the session to be tied to one specific Web Server ). session state runtime operation is implemented by the sessionstatemodule class which plugs into the request processing pipeline in the application as an ihttpmodule. sessionstatemodule executes once before handler execution in
The acquirerequeststate pipeline stage, and once after handler execution in the releaserequeststate pipeline stage (see
Figure 1). In the acquirerequeststate stage, sessionstatemodule attempts to extract the session ID from the request and retrieve the session data for that session ID from the session State store provider. if the session ID is present and
State is retrieved successfully, the module builds the session state dictionary that can be used by the handler to inspect and change the session state.
Figure 1
Maintaining session stateIn ASP. NET 2.0, session extraction is encapsulated in the session ID Manager component, which can be replaced by a custom implementation in order to support custom session ID management schemes (for example, storing the session
ID in a query string or in form fields ). the default session ID Manager supports both cookie-based and URL-based session IDs. the default ASP. NET 2.0 session ID Manager also provides support for automatically detecting which session ID mode shocould be used
Per request based on device profile or runtime negotiation with the client. if no session ID is present in the request, and the handler makes some changes to the session, a new session ID will be created in the releaserequeststate stage, and the new ID will be issued to the client by the session ID Manager
Implementation. in this case, and also if changes were made to an existing session, sessionstatemodule will use the State store provider to persist the changes made to session data for that session. in ASP. NET 2.0, the session State store functionality is encapsulated in the session store provider component, which can be one of the built-in inproc, sqlserver, or StateServer providers, or a custom provider that implements
The fetching of session data, the creation of sessions, and the saving of changes to existing sessions.
Improving performanceusing session state in an ASP. NET application can add noticeable overhead to the application performance. This shocould be expected as you are executing more code during the processing of every request in the application and possibly
Making network requests to retrieve stored state. however, there are several techniques your application can take advantage of to reduce the performance impact of session state use while still maintaining the desired state management functionality. the bulk of the session state processing that occurs on every request resides in sessionstatemodule. this module executes once before the ASP. net request handler to fetch the state for the session identified by the request information,
And once after the request handler to create a new session or to save the changes made to the existing session during handler execution. the inproc session state mode is the fastest of the built-in state storage modes. its overhead is limited to extracting the session ID from the request, specify a cache lookup for the State dictionary stored in the application's
Memory space, and marking the session as accessed to prevent its expiration. updates to the data contained in the session are made directly to objects in memory and do not require any additional work to be persisted for the next request. however, because
Inproc mode lacks the application restart tolerance and does not work in Web farm scenarios, the application frequently has no choice but to use one of the other two out-of-process modes. in the default out-of-process modes, sqlserver and StateServer, session state must be fetched from an external store and deserialized from its binary blob representation to the in-memory state dictionary form in the acquirerequeststate
Stage. in the releaserequeststate stage, the State dictionary needs to be serialized again and transferred to external storage. in addition, the session entry in the store must be updated to indicate the last access time to prevent its expiration. in these
Modes, serialization and deserialization of the state data, and its out-of-process transfer, are by far the most expensive operations introduced by session state to the Request Path. sessionstatemodule will perform a number of optimizations by default to avoid overhead wherever possible. these optimizations fall into four categories. first, for handlers or pages that are not marked as requiring session state, no session state work will be saved med into T for marking the session as accessed in the store. for pages marked as requiring read-only session state
Access, only the last-accessed marking and initial data fetching will be done. second, until any data is actually saved into the session dictionary, no session will be started for requests that do not already specify a session ID. third, on requests where no session state accesses are made or where only read accesses are made to session variables that contain immutable primitive types, no state changes will be persisted to the provider at the end of
Request. on requests where mutable session data was accessed or where the session was modified, only the accessed variables will be serialized and the rest will just be copied from their binary blob representations. and fourth, primitive types are serialized directly, but object types are serialized using the relatively slower binaryformatter serialization method. by taking advantage of these optimizations using the best practices has strated in this article, you can reduce the performance impact of session state management. the strategies discussed here focus on the three most promising
Approaches to improving application performance when using session state, taking advantage of the session state performance optimizations:
- Disabling session state when possible in order to avoid the overhead entirely.
- Cing the overhead of the serialization and deserialization of State data.
- Cing the overhead of out-of-process transfer of session state to and from the State store.
Disabling session statenot all pages in your application will need access to session state. for those pages that do not, You can indicate that session state is not needed and prevent session data from being fetched from the store in requests to these
Pages. for pages that do not update session state, you can indicate that read-only access is required. this does not prevent the State data from being fetched, but it results in a read lock being taken on the database, which enables
Multiple read-only requests to access the session simultaneously and prevents lock contention when multiple requests are made to the server with the same session ID. more importantly, it always prevents the session state module from connecting to the store
At the end of the request to update the state (there are other ways to avoid this also, which I'll describe later). Here's how you disable session state:
Copy code
<%@ Page EnableSessionState="False" %>
Similarly, this is how you indicate read-only session state:
Copy code
<%@ Page EnableSessionState="ReadOnly" %>
In fact, most typical pages such as shopping carts will only update the state if the user performs a PostBack action, like adding or removing an item from the cart, but not when she simply views the shopping cart. you can tweak application performance in this
Case by separating the viewing of the cart into its own page with read-only session state that does not perform an update. updating the shopping cart can be separated into another page to which the viewing page posts when an action is requested (cross posting
Is supported in ASP. NET 2.0 ).
You can also make the default behavior of the application be read-only or you can turn off session state by default by using the <pages> configuration element in your web. config file. then you can explicitly enable session state
Or Enable write access in only the pages that need it by setting the page enablesessionstate attribute appropriately, as shown here:
Copy code
<!--No session state by default--><configuration> <system.web> <pages enableSessionState="false" /> </system.web></configuration><!--Read-only session state by default--><configuration> <system.web> <pages enableSessionState="ReadOnly" /> </system.web></configuration>
Similarly, when you are building M handlers for processing requests in your application, you can disable session state by default by not implementing the marker interface system. Web. state. irequiressessionstate in your handler
Class. you can enable read-only mode by implementing the system. web. state. irequiresreadonlysessionstate marker interface instead of system. web. state. irequiressessionstate. note that if you turn off session state in your application, the httpcontext. session property will throw an exception if the page or handler tries to access it. if you mark the page as read-only, updates to the session in
Out-of-process modes will not be preserved into SS requests. in inproc mode, however, updates will be preserved because they are made to the live objects that stay memory-resident authentication SS requests. unfortunately, even when you turn off session state for a special page or handler, sessionstatemodule will still mark the session as accessed in the store, so an out-of-process connection to the store will be still be made when
Not using inproc mode. this is normally desired to prevent session expiration as long as the user is actively making requests to the application, regardless of whether the requests are to resources that require session state. but you may want to disable this
Behavior for some requests for performance reasons, especially if you are using ASP. net to serve images and page resources that are contained within a parent ASP. NET page that already has marked the session as active. to optimize this behavior, you can take advantage of the ASP. NET 2.0 custom session ID generation features to hide the session ID for a request, thereby preventing any session state work for that request. you can do this by implementing
A custom type that derives from system. Web. sessionstate. sessionidmanager, and then implementing the getsessionid method to return a null session ID for requests that do not require session state (see
Figure 2). For all other requests, you can delegate to the default getsessionid implementation of the sessionidmanager class, which provides the default cookie and cookieless session ID support in ASP. NET.
Figure 2 custom session ID Manager
Copy code
public class SessionDisablementIDManager : SessionIDManager{ // override the ID management behavior of the session ID manager public override String GetSessionID(HttpContext context) { // do not return the session ID if no session state is // desired for this request if (ShouldSkipSessionState(context)) return null; // otherwise just delegate to the built-in session // ID manager to get the session ID from the request else return base.GetSessionID(context); } protected virtual bool ShouldSkipSessionState(HttpContext context) { // determine if session state should be skipped for this request }}
There are some interesting ways to implement shouldskipsessionstate that avoid tracking session state. For example, you cocould skip session state when the request is for one of the extensions specified in your custom configuration
Section. you coshould also ignore session state when the current request handler instance (available as httpcontext. current. currenthandler) implements your own iskipsessionstate interface. you can make pages implement this interface by specifying your own page
Base class. Another scenario is when the current request handler instance does not implement irequiressessionstate and there was another recent request with this session ID on which session was marked as accessed. (You can keep track
Of this by writing your own M cookie, or by storing session ID/timestamp pairs in the ASP. net cache .) for example, if the last request that marked the session as active was less then 30 seconds ago, do not mark it as active now. this achieves the objective
And also does not seriously reduce the Session Activity window. you can deploy the custom session ID manager code in the app_code application directory, or you can compile it into an assembly and deploy it to the \ bin application directory or install it into the Global Assembly Cache (GAC ).
Then, to enable it, register it with session state configuration as follows:
Copy code
<configuration> <system.web> <sessionState sessionIDManagerType="IndustryStrengthSessionState. SessionDisablementIDManager"/> </system.web></configuration>
Note that if you employ this technique when using cookieless session IDs, some ASP. NET functionality that generates links or performs redirects that preserve the cookieless session ID will not work for the requests where you return
A null ID.