【Abstract]
You may have realized that with HTTP processing programs and modules, ASP. NET has provided powerful energy to developers. Insert your own component into the ASP. NET Request Processing pipeline and enjoy its advantages.
Introduction
At the beginning of the internetera, customers' needs can be met by a limited number of. HTM files. However, as the time passes, the expansion required by the customer exceeds the functions contained in the .htm file or static file.
Developers need to expand or expand the functions of web servers. Web server vendors have designed different solutions, but all follow the same topic "insert certain components to Web servers ". All complementary web server technologies allow developers to establish and insert components to Enhance web server functionality. Microsoft proposed ISAPI (Internet Server API), and Netscape proposed nsapi (webscape Server API.
ISAPI is an important technology that allows us to enhance the capabilities of ISAPI-compatible Web servers (IIS is a web server compatible with ISAPI. We use the following components to achieve this goal:
· ISAPI extension
· ISAPI filter
ISAPI extensions are implemented using Win32 dynamic link libraries. You can regard ISAPI extension as a common application. The objective of ISAPI scaling is to handle HTTP requests. This means you must call them to activate them. You can think that the ISAPI filter is just a filter. Each time the client sends a request to the server, the request goes through a filter. The client does not need to specify a filter in the request, but simply sends the request to the Web server. Then, the web server passes the request to the related filter. Next, the filter may modify the request and perform some login operations.
The complexity of these components makes it very difficult to implement them. Developers have to use C/C ++ to develop these components, but for many people, using C/C ++ for development is simply synonymous with pain.
So what does ASP. NET provide to implement these functions? ASP. NET provides httphandler (HTTP handler) and httpmodule (HTTP module ).
Before learning more about these components, it is valuable to know how HTTP requests are processed through the HTTP module and HTTP processing program.
Create a sample application
I have created the following C # projects to demonstrate different components of the application:
· Newhandler (HTTP handler)
· Webapp (demonstration of HTTP processing programs)
· Securitymodules (HTTP module)
· Webapp2 (demonstrate HTTP module)
Steps for installing these applications:
· Unlock the code in the attached ZIP file.
· Create two virtual directories: webapp and webapp2. Point these two directories to the actual physical directories of the webapp and webapp2 applications.
· Copy the newhandler. dll file in the newhandler project to the bin directory of the webapp.
· Copy the securitymodules. dll file in the securitymodules project to the bin directory of the webapp2 application.
Processing of ASP. NET requests
The ASP. NET Request Processing process is based on the pipeline model. In the model, ASP. NET passes the HTTP request to all modules in the pipeline. Each module receives HTTP requests and has full control permissions. The module can process requests in any way that it deems appropriate. Once the request passes through all the HTTP modules, it is finally processed by the HTTP processing program. The HTTP handler processes the request and the result will go through the HTTP module in the pipeline again:
Note that only one HTTP handler can be called during HTTP request processing, but multiple HTTP modules can be called.
HTTP handler
The HTTP handler is A. NET component that implements the system. Web. ihttphandler interface. Any class that implements the ihttphandler interface can be used to process input HTTP requests. The HTTP handler is similar to the ISAPI extension. The difference between HTTP processing programs and ISAPI extensions is that they can be directly called using the file names of HTTP processing programs in URLs, similar to ISAPI extensions.
The HTTP handler implements the following methods:
Method Name |
Description |
Processrequest |
This method is actually the core of the HTTP processing program. We call this method to process HTTP requests. |
Isreusable |
We call this attribute to determine whether the HTTP handler instance can be used to process requests of the same type. HTTP handlers can return true or false to indicate whether they can be reused. |
You can use the web. config or machine. config file to map these classes to HTTP requests. After the ing is completed, ASP. NET will instantiate the HTTP processing program when it receives the corresponding request. We will explain how to define all these details in the web. config and/or machine. config files.
ASP. NET also supports HTTP processing program extension through the ihttphandlerfactory interface. ASP. NET provides the ability to route HTTP requests to objects of classes that implement the ihttphandlerfactory interface. In addition, ASP. NET also utilizes the factory design mode. This mode provides an interface for creating a group of related objects without providing the function of a specific class. To put it simply, you can regard the class of the HTTP handler object used to establish the parameters passed in by dependencies as factory ). We do not need to specify the specific HTTP handler to be instantiated; the HTTP handler factory handles such transactions. The advantage of this is that if the implementation method of the object implementing the ihttphandler interface changes in the future, the client will not be affected as long as the interface is still the same.
The following is a list of methods in the ihttphandlerfactory interface:
Method Name |
Description |
Gethandler |
This method establishes an appropriate handler and returns its pointer to the calling code (ASP. NET runtime ). The handler object returned by this method should implement the ihttphandler interface. |
Releasehandler |
This method releases the HTTP processing program after the request is processed. The factory implementation determines its operations. The factory implementation can actually destroy the instance, or put it into the buffer pool for future use. |
Register an HTTP handler and an HTTP handler factory in the configuration file
ASP. NET maintains its configuration information in the following configuration file:
· Machine. config
· Web. config
The machine. config file contains configuration settings for all web applications installed on the computer.
The Web. config file is specific to each web application. Each web application has its own web. config file. Any subdirectory of the Web application may also contain its own web. config file, which allows them to overwrite the settings of the parent directory.
To add HTTP handlers to our web applications, you can use
<Httphandlers>
<Add verb = "supported HTTP Verbs" Path = "path" type = "namespace. classname, assemblyname"/>
<Httphandlers>
In the preceding XML,
The verb attribute specifies the HTTP action supported by the handler. If a processing program supports all HTTP actions, use "*". Otherwise, use a comma-separated list to list supported actions. Therefore, if your handler only supports http get and post, the verb attribute should be "Get, post ".
· The path attribute specifies the path and file name of the handler to be called (which can contain wildcards ). For example, if you want your handler to be in the test. the XYZ file is called only when it is requested, so the path attribute contains "test. XYZ ", if you want to include. all files with the XYZ suffix call the handler. The path attribute should contain "*. XYZ ".
· The type attribute specifies the actual type of the handler or handler factory in the form of a combination of namespace, class name, and part name. When ASP. NET is running, search for the part DLL in the bin directory of the application, and then search in the global part buffer (GAC.
How to Use http processing programs when ASP. NET is running
Whether you believe it or not, ASP. NET uses HTTP requests to implement a large number of its own functions. ASP. NET uses a handler to process. aspx,. asmx,. soap, and other ASP. NET files.
The following is a snippet in the machine. config file:
<Httphandlers>
<Add verb = "*" Path = "trace. axd" type = "system. Web. Handlers. tracehandler"/>
<Add verb = "*" Path = "*. aspx" type = "system. Web. UI. pagehandlerfactory"/>
<Add verb = "*" Path = "*. ashx" type = "system. Web. UI. simplehandlerfactory"/>
<Add verb = "*" Path = "*. config" type = "system. Web. httpforbiddenhandler"/>
<Add verb = "Get, head" Path = "*" type = "system. Web. staticfilehandler"/>
......
......
</Httphandlers>
In the configuration information above, you can see that all requests to the. aspx file are processed by the system. Web. UI. pagehandlerfactory class. Similarly, all requests to the. config file and other files (which cannot be directly accessed by the client) are processed by the system. Web. httpforbiddenhandler class. As you may have guessed, when accessing these files, this class simply returns an error message to the client.
Execute the HTTP processing program
Now you will see how to implement an HTTP handler. So what are the tasks for our new processing program? As I mentioned earlier, most handlers are used to add new features to Web servers; therefore, I will create a handler to handle new file types-files with the extension of. 15seconds. After we create this handler and register it in the web. config file of our web application, all requests to the. 15seconds file will be processed by this new handler.
You may be considering how to use this handler. What if you want to introduce a new server scripting language or dynamic server files (such as ASP and aspx? You can compile a processing program for it. Similarly, what if you want to run Java applets, JSP, and some other server-side Java components on IIS? One way is to install some ISAPI extensions (such as Allaire or Macromedia JRun ). You can also write your own HTTP processing program. Although this is a complicated transaction for third-party vendors (such as Allaire and Macromedia), it is an attractive choice because their HTTP processing can access ASP. all new features exposed during the net runtime.
To implement our HTTP handler, follow these steps:
1. Compile a class that implements the ihttphandler interface.
2. register the handler in the web. config or machine. config file.
3. In the Internet Service Manager, map the file extension (. 15 seconds) to ASP. net isapi extension DLL (aspnet_isapi.dll.
Step 1
Create a new C # class library project in Visual Studio. NET and name it "myhandler ". Visual Studio. NET automatically adds a class named "class1.cs" to the project. Rename it "newhandler". Open this class in the code window and change the class name and constructor name to "newhandler ".
The code for the newhandler class is as follows:
Using system;
Using system. Web;
Namespace myhandler
{
Public class newhandler: ihttphandler
{
Public newhandler ()
{
// Todo: add the construction logic here
}
# Region Implementation of ihttphandler
Public void processrequest (system. Web. httpcontext context)
{
Httpresponse objresponse = context. response;
Objresponse. Write ("<HTML> <body> Objresponse. Write ("</body> }
Public bool isreusable
{
Get
{
Return true;
}
}
# Endregion
}
}
You can see in the processrequest method that the HTTP handler accesses all ASP. net internal objects passed to it as parameters through the system. Web. httpcontext object. To implement the processrequest method, you only need to extract the httpresponse object from the context object and send some HTML to the client. Similarly, isreusable returns true, indicating that this handler can be used repeatedly to process other HTTP requests.
Compile the above Code and place it in the bin directory of the webapp virtual directory.
Step 2
In the Web. config file, add the following text to register the handler:
<Httphandlers>
<Add verb = "*" Path = "*. 15 seconds" type = "myhandler. newhandler, myhandler"/>
</Httphandlers>
Step 3
Since we have already created a handler for processing new extended files, we also need to inform IIS of this extension and map it to ASP. NET. If you try to access the hello.15seconds file without executing this step, IIS will simply return the file instead of passing it to ASP. NET runtime. The result is that the HTTP handler will not be called.
Run Internet Service Manager, right-click the default web site, select Properties, move to the Home Directory option page, and click Configure. The application configuration dialog box is displayed. Click the Add button, enter the aspnet_isapi.dll file path in the executable field, and enter. 15 seconds in the extended field. Other fields do not need to be processed. The dialog box is as follows:
Click OK to close the application configuration and default web site Properties dialog box.
Run Internet Explorer and enter URL: http: // localhost/webapp/hello.15seconds. The following page is displayed:
Dialog status in the HTTP handler
Maintaining the dialog state is the most common transaction executed by the web application. The HTTP handler also needs to access these dialog states. However, the default settings of the HTTP handler do not activate the dialog state. To read and/or write status data, the HTTP handler must implement one of the following interfaces:
· Irequiressessionstate
· Ireadonlysessionstate.
When the HTTP processing program needs to read and write the conversation data, it must implement the irequiressessionstate interface. If it only reads the conversation data, you can implement the ireadonlysessionstate interface.
Both interfaces are labeled and do not contain any methods. Therefore, if you want to activate the dialog state of the newhandler handler, declare the newhandler class like the following code:
Public class newhandler: ihttphandler, irequiressessionstate
HTTP Module
The HTTP module is a. NET component that implements the system. Web. ihttpmodule interface. These components register themselves in some events and insert themselves into the ASP. NET Request Processing pipeline. When these events occur, ASP. NET calls the HTTP module that is interested in the request, so that the module can process the request.
The HTTP module implements the following methods for the ihttpmodule interface:
Method Name |
Description |
Init |
This method allows the HTTP module to register its own event handler with the event in the httpapplication object. |
Dispose |
This method gives the HTTP module the opportunity to clean up objects before they are collected by garbage collection. |
The HTTP module can register with the following methods exposed to the system. Web. httpapplication object:
Event name |
Description |
Acquirerequeststate |
This event is triggered when ASP. NET is ready to receive the dialog status of the current HTTP request. |
Authenticaterequest |
This event is triggered when ASP. NET is running to verify the user identity. |
Authorizerequest |
This event is triggered when ASP. NET is ready to authorize users to access resources. |
Beginrequest |
This event is triggered when ASP. NET receives a new HTTP request. |
Disposed |
This event is triggered when ASP. NET completes HTTP request processing. |
Endrequest |
This event is triggered before the response content is sent to the client. |
Error |
This event is triggered when an unhandled exception occurs during HTTP request processing. |
Postrequesthandlerexecute |
This event is triggered when the HTTP processing program ends. |
Prerequesthandlerexecute |
This event is triggered before ASP. NET starts executing the HTTP request processing program. After this event, ASP. NET forwards the request to an appropriate HTTP handler. |
Presendrequestcontent |
This event is triggered before ASP. NET sends the response content to the client. This event allows us to change the response content before the content arrives at the client. We can use this event to add content for all pages to the page output. For example, general menu, header information, or foot information. |
Presendrequestheaders |
This event is triggered before ASP. NET sends the HTTP response header information to the client. Before the header information arrives at the client, this event allows us to change its content. We can use this event to add cookies and custom data to the header information. |
Releaserequeststate |
This event is triggered when ASP. NET ends the execution of the searched request handler. |
Resolverequestcache |
This event is triggered to determine whether the request can end with the content returned from the output buffer. This depends on how to set the web application output buffer. |
Updaterequestcache |
This event is triggered when ASP. NET processes the current HTTP request and the output content is ready to be added to the output buffer. This depends on how the web application's output buffer is set. |
In addition to these events, we can also use four events. We can use these events by implementing some methods in the global. asax file of Web applications.
These events are:
· Application_onstart
This event is triggered when the first request reaches the web application.
· Application_onend
This event is triggered before the application is terminated.
· Session_onstart
This event is triggered by the first request of the user conversation.
· Session_onend
This event is triggered when the conversation is abandoned or the conversation is out of date.
Register the HTTP module in the configuration file
After the HTTP module is created and copied to the bin directory of the Web application or Global Assembly Cache. config or machine. config.
We can use the
Because configuration settings can be inherited, subdirectories inherit configuration settings from the parent directory. As a result, subdirectories may inherit some unwanted HTTP modules (which are part of the parent configuration information). Therefore, we need a method to delete these unnecessary modules. You can use the <remove> node. If you want to delete all HTTP modules inherited from the application, you can use the <clear> node.
The following code is a common example of adding an HTTP module:
<Httpmodules>
<Add type = "classname, assemblyname" name = "modulename"/>
<Httpmodules>
The following code deletes an HTTP module from an application:
<Httpmodules>
<Remove name = "modulename"/>
<Httpmodules>
In the preceding XML:
· The type attribute specifies the actual type of the HTTP module in the form of class and part names.
· The name attribute specifies the friendly name of the module. Other applications can use this name to identify the HTTP module.
How to Use the HTTP module during ASP. NET running
The HTTP module is used to implement some special functions when ASP. NET is running. The following snippet is from the machine. config file. It displays the HTTP module installed during ASP. NET runtime:
<Httpmodules>
<Add name = "outputcache" type = "system. Web. caching. outputcachemodule"/>
<Add name = "session" type = "system. Web. sessionstate. sessionstatemodule"/>
<Add name = "windowsauthentication"
Type = "system. Web. Security. windowsauthenticationmodule"/>
<Add name = "formsauthentication"
Type = "system. Web. Security. formsauthenticationmodule"/>
<Add name = "passportauthentication"
Type = "system. Web. Security. passportauthenticationmodule"/>
<Add name = "urlauthorization"
Type = "system. Web. Security. urlauthorizationmodule"/>
<Add name = "fileauthorization"
Type = "system. Web. Security. fileauthorizationmodule"/>
</Httpmodules>
ASP. NET uses the preceding HTTP modules to provide some services, such as identity authentication and authorization, dialog management, and output buffering. These modules are registered in the machine. config file.
Implement an HTTP module that provides security services
Now we implement an HTTP module that provides security services for our web applications. The HTTP module provides a customized identity authentication service. It will receive the identity credential in the HTTP request and determine whether the credential is valid. If valid, what are the user-related roles? The user. Identity object is used to associate these roles with the user IDs that access our web application page.
The code of the HTTP module is as follows:
Using system;
Using system. Web;
Using system. Security. Principal;
Namespace securitymodules
{
/// Overall description of class1.
Public class customauthenticationmodule: ihttpmodule
{
Public customauthenticationmodule ()
{
}
Public void Init (httpapplication r_objapplication)
{
// Register the event handler with the application object.
R_objapplication.authenticaterequest + =
New eventhandler (this. authenticaterequest );
}
Public void dispose ()
{
// This field is empty because we do not need to perform any operations.
}
Private void authenticaterequest (Object r_objsender, eventargs r_objeventargs)
{
// Identify the user's creden。 and find out the user role ..
1. httpapplication objapp = (httpapplication) r_objsender;
2. httpcontext objcontext = (httpcontext) objapp. context;
3. If (objapp. request ["userid"] = NULL) |
4. (objapp. request ["password"] = NULL ))
5 .{
6. objcontext. response. Write ("7. objcontext. response. End ();
8 .}
9. String userid = "";
10. userid = objapp. request ["userid"]. tostring ();
11. String Password = "";
12. Password = objapp. request ["password"]. tostring ();
13. String [] strroles;
14. strroles = authenticateandgetroles (userid, password );
15. If (strroles = NULL) | (strroles. getlength (0) = 0 ))
16 .{
17. objcontext. response. Write ("Find this user ID and password in our database 18. objapp. completerequest ();
19 .}
20. genericidentity objidentity = new genericidentity (userid,
"Customauthentication ");
21. objcontext. User = new genericprincipal (objidentity, strroles );
}
Private string [] authenticateandgetroles (string r_struserid, string r_strpassword)
{
String [] strroles = NULL;
If (r_struserid.equals ("Steve") & (r_strpassword.equals ("15 seconds ")))
{
Strroles = new string [1];
Strroles [0] = "Administrator ";
}
Else if (r_struserid.equals ("Mansoor") & (r_strpassword.equals ("Mas ")))
{
Strroles = new string [1];
Strroles [0] = "user ";
}
Return strroles;
}
}
}
Let's take a look at the above Code.
We started from the init function. This function inserts the authenticaterequest event of the processing program into the event handler list of the Application object. This will cause the application to call this method when the authenticationrequest event is triggered.
After the HTTP module is initialized, we can call its authenticaterequest Method to Identify client requests. The authenticaterequest method is the core of the security/identity authentication mechanism. In this function:
Extract httpapplication and httpcontext objects in rows 1 and 2. Lines 3 to 7 check whether the user ID or password is not provided to us. If not, an error message is displayed and the request processing process ends.
Lines 9 to 12 extract the user ID and password from the httprequest object.
Line 14 calls a helper function called authenticateandgetroles. This function mainly performs authentication and determines the user role. The above Code uses hard-coded and only allows two users to use it. However, we can extend this method and add code to interact with the user database and retrieve the user's role.
Lines 16 to 19 check whether a role is associated with the user. If not, it means that the credential passed to us has not passed verification; therefore, this credential is invalid. Therefore, an error message is sent to the client and the request is complete.
Lines 20 and 21 are very important, because these two lines Actually tell ASP. Net the identity of the logged-on user during HTTP runtime. After these two rows are successfully executed, our ASPX page will be able to access this information using the user object.
Now let's take a look at the status of this authentication mechanism. Currently, only the following two users are allowed to log on to the system:
· User id = Steve, password = 15 seconds, role = Administrator
· User id = Mansoor, password = mas, role = user
Note that the user ID and password are case sensitive (case sensitive ).
First, try to log on to the system without providing a credential. Enter http: // localhost/webapp2/index. aspx in IE to see the following message:
Now I am trying to log on to the system using the user ID "Steve" and password "15seconds. Enter http: // localhost/webapp2/index. aspx? Userid = Steve & Password = 15seconds you will see the following welcome message:
Now I am trying to log on to the system using the user ID "Mansoor" and the key code "Mas. Enter http: // localhost/webapp2/index. aspx? Userid = Mansoor & Password = mas you will see the following welcome message page:
Try to use the wrong combination of user ID and password to log on to the system. Enter http: // localhost/webapp2/index. aspx? Userid = Mansoor & Password = xyz you will see the following error message:
This indicates that our security module is working. You can use the database access code in the authenticateandgetroles method to expand the security module.
To make all parts work, we must make some modifications to the Web. config file. First, because we need to use our own authentication, no other authentication mechanism is required. To achieve this, change the <authentication> node in the web. config file of webapp2, as shown below:
<Authentication mode = "NONE"/>
Similarly, anonymous users are not allowed to access our web site. Add the following statement to the Web. config file:
<Authorization>
<Deny users = "? "/>
</Authorization>
Used to access at least the files used to provide creden anonymously. In the Web. config file, use the following configuration settings to use index. aspx as the only file that can be accessed anonymously:
<Location Path = "index. aspx">
<System. Web>
<Authorization>
<Allow users = "*"/>
</Authorization>
</System. Web>
</Location>
Conclusion
You may have realized that with HTTP processing programs and modules, ASP. NET has provided powerful energy to developers. Insert your own component into the ASP. NET Request Processing pipeline and enjoy its advantages.
As an exercise, you should further improve the program to make the sample Authentication Module more flexible and make adjustments as needed.
Trackback: http://tb.blog.csdn.net/TrackBack.aspx? Postid = 1133223