Based on various considerations, there are three custom solutions for session state management:
1. Retain the default session module, but write a custom State provider to change the storage medium. In this way, we also have the opportunity to rewrite some helper classes used to carry session data between the storage and session.
2. Retain the default session module, but replace the session ID generator.
3. Replace the default session Status Module with your own. This method provides the best flexibility, but it is also the most complex. We recommend that you use this solution only when you are sure to know the exact implementation method.
Build a custom session Status provider
The session Status provider is a component that serves the current session data. When a request requires status information, the component is called to obtain data from the specified storage medium and return the data to the master module. When the request ends, it is also called to write the provided data to the storage layer.
ASP. NET supports three state providers, which are described in the following table:
We can also write our own State provider class so that our applications can choose their preferred storage media.
Define session state storage
The status provider is a class inherited from sessionstatestoreproviderbase. The following table lists the main methods of its interfaces:
Inherit the sessionstatestoreproviderbase class and retain the default ASP. NET session Status Module. In this solution, only session status data storage and data recovery functions can be changed. Other functions cannot be changed.
Lock and expiration
The status provider must implement the locking mechanism for continuous session access. The session Status Module can determine whether the request requires read-only access in the session state or read/write access. Based on the judgment result, it will call getitem or getitemexclusive. In the implementation of these two methods, the compiler of the provider should create a locking mechanism for read/write sessions, allowing multiple concurrent read operations, however, you must prevent data from being written to a locked session.
Another problem is that the session Status Module needs to know the expiration time of a specified session. If global. asax defines the session_end event handler, the session Status Module calls setitemexpirecallback. By using this method, the status provider will get a callback function. Its prototype is as follows:
public delegate void SessionStateItemExpireCallback(string sessionID, SessionStateStoreData item);
The session module stores the returned delegate internally and calls it when the specified session times out. Expired callback support is optional. In fact, only inproc actually supports it. If you do not want custom providers to support expiration callback, you should instruct the setitemexpirecallback method to return false.
To support providers without Cookie sessions, you must also implement the createuninitialized method to write null session items to data storage. Specifically, an empty session item is a complete data item, but does not contain actual data. That is to say, the session item should contain the session ID and creation time (which may also contain the lock ID), but not the data. For ASP. NET 2.0, in non-Cookie mode, a new ID is generated when a request is sent after the session expires. Session status mode generates a new ID and redirects the browser. If the uninitialized session item is not assigned a new ID, the new request will still be considered as a request in an expired session.
Replacement of the session data dictionary
Sessionstatestoredata is a class that represents session Items (a data structure that contains all session-related data ). In fact, instances of this class are returned by getitem and getitemexclusive. This class has three attributes: items, staticobjects, and tiemout.
Items is used to provide data for the key/value set in the session attribute of the page object. Staticobjects contains static objects that belong to the current session (for example, objects declared in global. asax and visible in the session range ). Timeout is the effective time (in units) of the session state. The default value is 20 minutes.
Once the session status module obtains the session status for a request, it writes the content of the items set to a new instance of the httpsessionstatecontainer class. The object is then passed to the constructor of the httpsessionstate class and becomes the data container behind the session attribute.
For the session module and status provider, the container of the session item is only a class that implements the isessionstateitemcollection interface. By default, the instance uses the sessionstateitemcollection class. As long as the custom class implements the preceding interface, it can replace the sessionstateitemcollection class.
To write a State provider, the sessionstateutility class is very useful. It contains methods for serializing and deserializing session items so that they can be stored in a media or read. In addition, this class also has some methods to extract data dictionaries from sessions and add them to HTTP context and session attributes.
Registration of the custom session Status provider
To enable the application to use a custom session Status provider, We need to register it in the web. config file. Assume that a provider class named samplesessionstaeprovider is compiled into a mylib assembly:
<system.web>
<sessionState mode="Custom"
customProvider="SampleSessionProvider">
<providers>
<add name="SampleSessionProvider"
type="SampleSessionStateProvider, MyLib" />
</providers>
</sessionState>
</system.web>
Custom session ID generation
To generate a session ID, ASP. NET 2.0 uses the component sessionidmanager. This class is neither an HTTP module nor a program, but a class that inherits from system. Object and implements the isessionidmanager interface. As long as the isessionidmanager interface is implemented, the custom class can replace this component.
Default behavior
The default session ID module generates session IDs in the form of byte arrays and encrypts strongly random sequences with 15 values. The data is then encoded as a string containing 24 characters, and each character complies with the URL standard. The system uses the session ID.
The session ID can be transmitted between the server and the client through an HTTP cookie or a modified URL, depending on the value of the cookieless attribute in <sessionstate>. Note: If a cookie-free session is used, the session ID module is responsible for adding the ID to the URL and redirecting the browser. The default generator redirects the browser to the following virtual URL:
Http://www.contoso.com/test/ (S (session_id)/page. aspx
How can requests from such URLs be correctly processed? In the absence of cookie sessions, the session ID module uses a lightweight ISAPI filter (aspnet_filter.dll) to dynamically rewrite the input URL to implement the resource URL. The request will be processed correctly, but the path in the address bar will not change. The detected session ID is placed in a header called aspfiltersessionid.
Self-made session ID Manager
Session ID manager is a class that implements the isessionidmanager interface. Therefore, we have two solutions to build it:
1. Create a new class and implement this interface.
2. derive a class from sessionidmanager and override two virtual methods (createsessionid and validate) to implement some special logic.
The isessionidmanager interface is described in the following table:
If you plan to use a fully custom session ID generator, pay attention to the following points:
1. The algorithm for generating IDS is critical. If strong random encryption is not implemented, malicious users may guess valid IDs when some sessions are active. Therefore, generating a global GUID is a good choice.
2. We can choose whether to support cookie-free sessions. If such support is added, the component must be able to extract session IDs from HTTP requests and redirect the browser. Therefore, the ISAPI filter or HTTP module may be required to pre-process the request and modify it as appropriate.
After creating the session ID module, you can register it in the configuration file:
<sessionState sessionIDManagerType="Samples.MyIDManager, MyLib" >
</sessionState>