
Asp Net 2.0 Security Membership And Role Management
.pdf
Chapter 6
Figure 6-1
The Application Configuration dialog box, shown in Figure 6-2, in IIS6 now has two sections: one where you can adjust one-to-one associations of file types to specific ISAPI extensions and a new section at the bottom where you can set up one or more wildcard mappings.
Unless you have a photographic memory, you probably don’t remember the full path to the ASP.NET ISAPI extension. So, before configuring wildcard mappings, it is helpful to select one of the preexisting mappings (for example, the .aspx mapping) and click the Edit button. The Add/Edit Application Extension Mapping dialog box, shown in Figure 6-3, conveniently holds the full path to the ASP.NET ISAPI extension in the Executable text box.
262

Integrating ASP.NET Security with Classic ASP
Figure 6-2
Figure 6-3
263

Chapter 6
Copy the path and then cancel out of the dialog box. Now you can click the Insert button in the bottom half of the Application Configuration dialog box to open the dialog box for configuring wildcard extension mappings (Figure 6-4.) Paste in the full path to the ASP.NET ISAPI extension into the Executable text box.
Figure 6-4
Close out of all of the dialog boxes by clicking OK. You have now configured an application inside of IIS6 that will forward all requests initially to the ASP.NET 2.0 ISAPI extension. Due to the new functionality of the DefaultHttpHandler inside of ASP.NET 2.0, these requests will handed off to IIS6 for execution by the appropriate extension or internal runtime logic. After the appropriate extension or IIS6 had completed its processing, ASP.NET 2.0 will have the chance to perform some postprocessing, after which the request will complete.
For now just a simple ASP page is used:
<%
Response.Write(“This is text from the classic ASP application” + “<br/>”) %>
When you access this page (in the sample application this is default.asp), the classic ASP ISAPI extension (ASP.dll) will eventually get the chance to parse and run the page, resulting in a string being output to the browser. If you happen to run into a 404 error trying this on IIS6, remember that on IIS6 all known dynamic content extensions are disabled by default, including classic ASP. If you need to enable classic ASP, use the IIS MMC, as shown in Figure 6-5, to enable it again.
It’s time to get a little frisky and see if ASP.NET can output some text in addition to the text coming from the classic ASP application. Try adding the following code to global.asax:
void Application_BeginRequest(Object sender, EventArgs e)
{
HttpContext.Current.Response.Write(“This came from the ASP.NET global.asax event hander”);
}
264

Integrating ASP.NET Security with Classic ASP
Figure 6-5
When you run default.asp, instead of getting back two pieces of text (one from ASP.NET and one from classic ASP), you instead get an error saying, “This type of page is not served.” Hmmm — what happened? First everything was working with the wildcard mapping, and now that you add one simple line of code to ASP.NET and everything breaks!
The reason for this behavior is quite simple. When ASP.NET detects that a response has been modified, prior to handing the request back to IIS6 it checks to see if the request was either a POST request, or a request for a classic ASP page. If the request is a POST request or a classic ASP request ASP.NET will throw an exception rather than hand control back to IIS6. ASP.NET considers a response to have been modified if any of the following occur:
265

Chapter 6
One or more HTTP headers in the response have been set or modified (for example setting a cookie).
Text has been written to the response, regardless of whether this text has been buffered or already sent to the client.
Code in the ASP.NET application modified the HttpCachePolicy associated with the response.
A Stream was assigned to the Response.Filter property. This is an advanced operation and is normally used by developers who need to modify the raw contents of the response prior to sending it back to the browser.
The last two restrictions probably aren’t particularly onerous for developers. However, the first two restrictions effectively mean that you need to be careful about what an ASP.NET application is doing when you use it as a wildcard mapping. If you think about it though, these restrictions do make sense; ASP.NET and classic ASP still live in separate worlds and know nothing about the internal processing logic of the other’s ISAPI extension.
Without some major surgery to the guts of IIS, ASP, and ASP.NET, it is basically impossible for two ISAPI extensions to manipulate the data that is sent back in a response. For example, how would you integrate ASP.NET’s fragment caching with the response written from a classic ASP page? Or how would the response buffering behavior in classic ASP (the Enable Buffering check box for ASP) coexist with response buffering in ASP.NET? The simple answer is that both ISAPI extensions have many internal assumptions about a request lifecycle and around ownership of the actual response data. There isn’t any easy way to reconcile these assumptions in ASP.NET 2.0 or IIS6.
As a side note: This type of coordination is in large part what IIS7 is all about. With support for an integrated pipeline in IIS7, different dynamic content processors like ASP.NET and classic ASP will have a more coherent way of interacting with the request and response data. Though whether either ISAPI extension will be reworked sufficiently to allow ASP.NET and classic ASP to output request content remains to be seen.
Now that you understand that ASP.NET cannot touch anything in the response when interacting with classic ASP, what are some of the things you can safely do in ASP.NET? Any ASP.NET APIs that don’t touch the response are safe to use. So, for example, you can call any of the following:
Forms authentication APIs that create tickets as well as encrypting and decrypting string representations of the tickets. However you cannot call methods like SetAuthCookie or
RedirectFromLoginPage.
Application services that don’t directly interact with the Response object are safe to call. You could call most of the Membership, Role Manager and Profile APIs without any problems.
You can freely use the Request object to inspect information; you could look at the forms authentication cookie (if one was sent) or query-string and forms variables.
You can access other application services such as session state or the Cache API.
As a simple example, you can take the sample ASP.NET application used earlier, and instead of touching the Response, log information about the incoming request to a text file:
266

Integrating ASP.NET Security with Classic ASP
void Application_BeginRequest(Object sender, EventArgs e)
{
//HttpContext.Current.Response.Write(“This came from the ASP.NET global.asax event hander”);
StreamWriter sw = File.CreateText(Server.MapPath(“~/App_Data/logfile.txt”)); sw.WriteLine(“A request was made to: “ + Request.Path);
sw.Flush();
sw.Close();
}
If you access default.asp, everything still works, and the ASP.NET applications App_Data directory contains the text log file containing information about the request. So, you can safely carry out complex operations from inside of the ASP.NET application. From a design standpoint, this means you can think of a wild-carded ASP.NET application as something of a bridge to the managed world for a classic ASP application.
At this point, you might be thinking there is a sneaky way to start doing interesting “stuff” inside of ASP.NET and then pass the results off to classic ASP. Obviously, from the previous sample you could hack up an approach whereby ASP.NET writes information to a file in a common location, and classic ASP read from it. But that approach is going to fall apart quickly. How about just stuffing information onto the query string inside of ASP.NET and then picking these values up over in the classic ASP code?
Request.QueryString.Add(“foo”, “It would be nice if this worked.”);
This code is a nice idea, but it isn’t going to work because inside of ASP.NET information such as Request.QueryString and Request.Form are contained in read-only collections. You could write code inside of the classic ASP application that would place values on the query-string, and then when a redirect occurred the ASP.NET application could read these values and do some work, but the problem that is being addressed in this chapter involves authentication and authorization. In these cases, the flow of data is in the other direction; you need ASP.NET to communicate the results of an authentication or authorization decision to the classic ASP application (or at least store the results in a way that protects the classic ASP application).
Of course, the issue with using all of the ASP.NET capabilities is that the results are still “locked up” as it were inside of the ASP.NET application. How do you actually throw any of the data over the wall to the classic ASP application? Prior to ASP.NET 2.0, you would probably pursue options such as:
Write a Web Service that wraps managed code, and then access it using SOAP tools from your classic ASP applications
Wrap the managed code into a COM component thus making the logic available to the classic ASP world as well.
Both of these approaches are still valid in the world of ASP.NET 2.0. However, they also tend to be a bit heavyweight. Writing a Web Service or a COM-callable wrapper to an inventory control API might make sense, sometimes all you want to accomplish is basic authentication and authorization. Even for these two aspects of a website, writing a Web Service and making something like forms authentication globally available as a service can be appealing.
267



