Please let other users know how useful this tip is by rating it at the bottom of this page. Do you have a tip or code of your own you'd like to share? Submit it here for your chance to win a free .NET programming book in our monthly tip contest!


Learn how -- and how not -- to share Session variables between your old and new apps.

As you migrate your Web apps from classic ASP to ASP.NET, you may not have the luxury of completely rewriting the entire application before going to production. Instead, you may need to migrate portions of the application from ASP to ASP.NET, while leaving others as-is. If you need to make this type of migration, you will inevitably encounter the issue of how to integrate session state from your ASP application into your ASP.NET app.

Unfortunately, the session management services for each technology are completely separate, and there is no standard mechanism for sharing information between an ASP and an ASP.NET session. This article, however, shows a secure and simple method of sharing Session variables between ASP and ASP.NET pages. Along the way, you'll also learn about several alternative methods that are not secure.

Must-haves and must-nots

Any solution to the ASP/ASPX session sharing issue needs to address certain issues. First, it must be secure. Given that highly sensitive information is typically kept in session variables, security must be considered. A breach in a session sharing mechanism could result in a major system breach.

Next, it should be elegant. A complex solution or one that is difficult to maintain would be counterproductive. After all, this solution is most likely a temporary solution until all of an application can be migrated to ASP.NET pages.

Finally, it should require minimal server-based components beyond ASP.NET and ASP-based pages (or better yet, none at all). Many sites are hosted on remote servers; getting a vendor to run your DLL or other system file can be challenging.

Typically, information stored in a Session variable is for internal application use only and should be considered to be highly secure. Things that are often stored in the Session object include login state, user information, system information, and many potentially other secure items that an end user should never see. Given the secure nature of information that is stored in a Session object, security must be the paramount concern. With that in mind, some of the obvious solutions to the Session sharing issue must be avoided because they are extremely insecure. You should never put sensitive information in a cook!e, a hidden parameter, or a URL; and you should avoid returning secure or system information to a browser, unless it's absolutely necessary.

The big question

HTTP is a stateless protocol. A request is sent by the client to the server and a response is returned to the client. The connection is then completed. The nature of this sessionless protocol has led vendors (like Microsoft) to come up with alternative means of maintaining session state outside the base HTTP protocol. In general, session state is maintained by ASP via the use of a cook!e that is sent from the server to the client. If you look at the HTTP response, you'll see something like this:

HTTP/1.1 200 OK 
Server: Microsoft-IIS/5.0 Date: Mon,07 Apr 2003 12:52:26GMT
Content-Length: 10225
Content-Type: text/html
Cache-control: private
Set-Cookie: ASPSESSIONIDCSCRRCBS=GODPKFJDPJNMHGGJDOEIDDMK;

Note that the Web server (IIS) set a cook!e with a name that starts with ASPSESSION and has some seemingly random value. This is the ASP Session cook!e. All subsequent requests sent from the client to the server will include the ASP Session cook!e along with the request. This cook!e allows IIS to associate the request with a specific session object that is stored on the server.

ASP.NET uses the same technique to maintain session state, except that a different cook!e name is used. In the case where an ASP session and an ASP.NET session have been established with the same server, the browser will send both the ASP and ASP.NET cook!es with each request. The request will look something like this:

GET /MixedSessions/ASPSession.aspx HTTP/1.0 
...headers removed to simplify example...
Cookie: ASPSESSIONIDAAR=NGHNLJKBBJG;
ASP.NET_SessionId=q5ydd3t45....

From this we know that if you have ASP and ASP.NET applications running in the same folder (specifically if you put the ASP and ASP.NET files in the same folder or virtual directory), the user will have a Session object in both the ASP and ASP.NET environments. The question now becomes how you can share information in the ASP environment with the ASP.NET environment.

All together now

The goal of this solution is to allow an ASP.NET app to retrieve variables from an ASP Session object. Figure 1 illustrates the flow of the process that occurs:

  1. A user's browser will send a request from the client to the server. This request will contain the ASP and ASPX Session tokens (cook!es).
  2. An ASPX Web page that needs information from an ASP Session object will create an HTTP request and send it to an ASP page that is specifically designed to return ASP Session object variables securely.
  3. The ASP page will authenticate that the request is from a local ASP.NET page only. Then it will look up the requested Session variable and return it in the HTTP response.
  4. The ASP.NET page will do whatever processing is needed and generate the response.
  5. The response is returned to the user.

Figure 1
Figure 1. By using a .NET class that creates a request containing the ASP Session cook!e and sends it to an ASP page to retrieve the ASP Session variable and an ASP page that authenticates the request and returns the Session variable, you can share Session state between ASP.NET and ASP apps.

In Step 2 above, the ASP.NET page will craft a request that contains the ASP Session cook!e that was passed to it. This will allow the ASP page to associate the request that comes from the ASPX page with the proper user's session.

Two components will be needed to make this system work. The first is a .NET class that will create a request that contains the ASP Session cook!e and sends it to an ASP page to retrieve the ASP Session variable. The second will be the ASP page that authenticates the request and then returns the Session variable.

The .NET code consists of two main functions and a constructor. The two functions work together to request Session information from an ASP page and the constructor decides to which ASP page the necessary request will be sent.

The constructor for this class takes a reference to the HttpContext and derives the URLit will need to send its requests to, as shown in Figure 2.

public ASPSessionVar(HttpContext oInContext) 
{
oContext = oInContext;
ASPSessionVarASP = "SessionVar.asp";
/* We now build a System.Uri object to derive the correct
URL to send the HTTP request to. oContext.Request.Url
will contain a System.Uri object that represents
this ASPXs URL.
*/
System.Uri oURL = oContext.Request.Url;
ASPSessionVarASP = oURL.Scheme + "://" + oURL.Host + ":" + oURL.Port.ToString() + ASPSessionVarASP;
}
Figure 2. The ASPX page is going to make an HTTP request to an ASP page contained in the same folder as this ASPX page. This section of code derives the proper URL to send the request to. 

The primary function for this example is called GetSessionVar, which is shown in Figure 3. It does the majority of the work done by this application as outlined in Step 2 of Figure 1. This includes creating a WebRequest, sending it off to the ASP page, and returning the response.

public string GetSessionVar(string ASPSessionVar) 
{
// First get the Session Cookie
string ASPCookieName = "";
string ASPCookieValue = "";
if (!GetSessionCookie (out ASPCookieName,out ASPCookieValue))
{
return "";
}
// Initialize the WebRequest.
HttpWebRequest myRequest = (HttpWebRequest) WebRequest.Create(ASPSessionVarASP + "?SessionVar=" + ASPSessionVar);
myRequest.Headers.Add("Cookie: " + ASPCookieName + "=" + ASPCookieValue);
// Send the request and get a response
HttpWebResponse myResponse = (HttpWebResponse) myRequest.GetResponse();
Stream receiveStream = myResponse.GetResponseStream();
System.Text.Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
StreamReader readStream = new StreamReader(receiveStream, encode);
string sResponse = readStream.ReadToEnd();
// Do a bit of cleanup
myResponse.Close();
readStream.Close();
return sResponse;
}
 Figure 3. GetSessionVar is the primary function in this example. It handles the process of creating, sending, and parsing the HTTP request that is used to retrieve the ASP session variable. 

One utility function that is used is GetSessionCookie, shown in Figure 4. This function simply takes the Request that was passed by the client and extracts the ASP Session cook!e from it. This function is called by the GetSessionVar function to retrieve the ASPSession cook!e. Since this ASP/ASPX-based application is on the same server the Web browser will send both the ASP and ASPX cook!es with each request that is made to the Web server. This function iterates through the cook!es that are contained in the Cookies collection and finds and returns the ASPSession cook!e.

private bool GetSessionCookie (out string ASPCookieName, out string ASPCookieValue) { 
int loop1; HttpCookie myCookie;
// Cookie variable
ASPCookieName = "";
ASPCookieValue = "";
// Capture all cook!e names into a string array.
String[] CookieArray = oContext.Request.Cookies.AllKeys;
// Grab individual cook!e objects by cook!e name.
for (loop1 = 0; loop1 < CookieArray.Length; loop1++) {
myCookie = oContext.Request.Cookies[CookieArray[loop1]];
if (myCookie.Name.StartsWith("ASPSESSION")) {
ASPCookieName = myCookie.Name;
ASPCookieValue = myCookie.Value;
return true;
}
}
return false;
}

Figure 4. The GetSessionCookie function will find and return the ASPSession cook!e that was sent by the browser in the HTTP request and return it to the GetSessionVar function.

Serve the session variable

The ASP code for this example was placed in an ASP file called SessionVar.asp. It performs two simple tasks. First, it ensures that the request is coming from the server that the ASP page is running on. This ensures that the request is valid and coming ONLY from the Web server's IP address. The ASP page then returns the session variable it was asked to provide:

<% 
dim sT
if Request.ServerVariables("REMOTE_ADDR") = Request.ServerVariables("LOCAL_ADDR") then
sT = Request("SessionVar")
if trim(sT) <> "" then
Response.Write Session(sT)
end if
end if
%>

It is critically important that the IP address check not be removed for any reason. Removing this would allow a hacker to access potentially critical information.

The following code shows how this class can be used by an ASPX-based Web page that needs to retrieve Session from an ASP-based application. The ASPX page will instantiate an ASPSessionVar object, passing in the current Context to the constructor. The GetSessionVar function is then called, passing in the name of the ASP Session variable that is to be retrieved. No other setup is required to call the method:

//Create an ASPSessionVar object, 
//passing in the current context
SPI.WebUtilities.ASP.ASPSessionVar oASPSessionVar = new SPI.WebUtilities.ASP.ASPSessionVar(Context);
string sTemp = oASPSessionVar.GetSessionVar("FirstName");

After executing a call to the GetSessionVar function the sTemp variable will contain the contents of the FirstName session variable from the ASP-based application.

Dennis Hurst is a senior consulting engineer for SPI Dynamics and is a member of its SPI Labs team of Internet security experts. He is responsible for working with customers and for developing marketing resources that educate them on the need for Web application security and practical ways to protect Web sites by using WebInspect, the company's flagship product line of Web application security assessment solutions. Dennis is an MSCD in Visual Basic and SQL Server. You can reach Dennis at dhurst@spidynamics.com.


This article was provided by asp.netPRO Magazine, an online information resource for the ASP.NET developer community, which helps professional software developers build, deploy and run the next generation of dynamic, distributed Web applications quickly and easily. Click here to learn more.

Posted by 퓨전마법사
,