1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu ASP.NET 1.1 Insider Solutions- P12 ppt

50 323 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 50
Dung lượng 515,6 KB

Nội dung

Building a Custom Authentication Module Authentication is the process of identifying users. Authentication modules use evidence in each request made to the application to identify which user is making the request. The authentica- tion modules that ship with ASP.NET use as their evidence encrypted cookies in the request (forms authentication and Passport authentication) and evidence provided by IIS (Windows authentication). What Is an Authentication Module? In code terms, an authentication module is an HTTP module that handles the AuthenticateRequest event of the HttpApplication object. When the event fires, the authentication module checks the evidence associated with the request and populates the Context.User intrinsic object with an appropriate IPrincipal object (that is, an object of a class that implements the IPrincipal inter- face). The authorization module then uses Context.User as the basis for deciding whether the request should be authorized. The rest of the application code is then able to access whatever data is stored in the IPrincipal object. It is actually pretty rare that you need to replace the standard authentication modules with a custom solution. Usually you can solve your problems by customizing one of the existing modules. Forms authentication, as you saw in Chapter 13, is particularly suitable for such manipulation. One situation in which a custom authentication module is useful is when you want to identify access to an application according to which machine is trying to access the application rather than according to which specific user is making the request. For example, if you have an intranet application running on a closed network in a shopping mall, you might want to iden- tify which client machines are used to make requests in order for the application to behave differently. (For example, the application might show special offers appropriate to stores near the client machine that is being used, or the map might be able to show a “you are here” label.) There are all sorts of ways you can solve this problem. One clean way is to implement a custom authentication module that uses the IP address of the client machine as the evidence for authentication. The following sections show how to build a simple HTTP module that provides this functionality. Building a Custom Identity Class Before you build the HTTP module itself, you need to think about the IPrincipal object that it will use to populate Context.User . The principal represents the security context of the user. The interface has the following members: Member Return Type Identity IIdentity IsInRole (String) Boolean 14 Customizing Security 538 19 0672326744 CH14 5/4/04 12:27 PM Page 538 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 539 Building a Custom Authentication Module Every IPrincipal object will store an IIdentity object that represents the identity of the authen- ticated user and will allow you to check whether the user is in a particular role. You can build a custom class that implements IPrincipal , but there is rarely any need to do so; System.Security.Principal.GenericPrincipal does the job in the vast majority of cases. GenericPrincipal provides a constructor that takes an IIdentity object and an array of strings for the roles. It simply stores the roles internally and checks against them when IsInRole is called. Most authentication approaches can use GenericPrincipal . The exception is Windows authenti- cation, which needs to check roles against the user’s Windows roles rather than against a set of roles stored by the principal object. It therefore defines a different IPrincipal implementation, WindowsPrincipal . In the IP authentication example, GenericPrincipal will do just fine. However, you should create a custom identity class that implements IIdentity . The reason becomes clear when you look at the members required by the IIdentity interface: Member Return Type AuthenticationType String IsAuthenticated Boolean Name String The identity needs to return the type of authentication used to create it, so a new identity class is needed for each authentication module. The following is the code for an identity class for the IP authentication module: Public Class IPIdentity Implements System.Security.Principal.IIdentity Private _IP As String = Nothing Public Sub New(ByVal ip As String) _IP = ip End Sub ‘do not allow an IPIdentity to be created without an IP address Private Sub New() End Sub Public ReadOnly Property AuthenticationType() As String _ Implements System.Security.Principal.IIdentity.AuthenticationType Get Return “IP” End Get End Property Public ReadOnly Property IsAuthenticated() As Boolean _ Implements System.Security.Principal.IIdentity.IsAuthenticated 19 0672326744 CH14 5/4/04 12:27 PM Page 539 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Get ‘An IP Identity will only be used when authentication is successful Return True End Get End Property Public ReadOnly Property Name() As String _ Implements System.Security.Principal.IIdentity.Name Get Return _IP End Get End Property End Class You store the IP address of the machine that is making the request in a private field. A construc- tor is provided to allow a new IPIdentity object to be created from an IP address, but you mark the default constructor as private so it cannot be used. The members required by IIdentity are each provided. AuthenticationType returns “IP” . IsAuthenticated returns true; you will be using IPIdenity only with authenticated requests. Name returns the IP address string. This is a pretty minimal IIdenity implementation. You can add other data to the identity class. For example, FormsIdentity provides access to the forms authentication ticket. Building the HTTP Module Now that you know what the IP authentication module is going to populate Context.User with, you can press on and build the HTTP module that will implement it (see Listing 14.1). LISTING 14.1 An HTTP Module Implementation for IP-Based Authentication Imports System.Security.Principal Public Class IPAuthenticationModule Implements IHttpModule Public Sub Dispose() Implements System.Web.IHttpModule.Dispose ‘we have no resources to dispose of End Sub Public Sub Init(ByVal context As System.Web.HttpApplication) _ Implements System.Web.IHttpModule.Init ‘handle the AuthenticateRequest of the application AddHandler context.AuthenticateRequest, AddressOf Me.Authenticate End Sub 14 Customizing Security 540 19 0672326744 CH14 5/4/04 12:27 PM Page 540 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 541 Building a Custom Authentication Module Public Sub Authenticate(ByVal sender As Object, ByVal e As EventArgs) Dim application As HttpApplication = CType(sender, HttpApplication) ‘create identity and principal objects Dim identity As New IPIdentity(application.Request.UserHostAddress) Dim principal As New GenericPrincipal(identity, New String() {}) ‘attach the principal to the application context application.Context.User = principal End Sub End Class You don’t need to do anything in the Dispose method because you use no resources that require disposal. You have to include it, though, because it is required by the IHttpModule interface. In the Init method, you bind the Authenticate method of this class to the AuthenticateRequest event of the application. In the Authenticate method, you simply use the IP address of the request ( Request.UserHostAddress ) to create an IPIdentity object, which is then used to construct a GenericPrincipal instance that is stored in Context.User . Before the module can be used, you need to ensure that no other authentication modules are active by setting the <Authentication> element of the web.config file appropriately: <authentication mode=”None” /> You also need to add an <httpModules> section to the web.config file to add the module to the application: <?xml version=”1.0” encoding=”utf-8” ?> <configuration> <system.web> <httpModules> <add type=”CustomAuthentication.IPAuthenticationModule, ➥CustomAuthentication” name=”IPAuthentication” /> </httpModules> After you have done this, you can access the IP address of the client through Context.User. Identity.Name . (This is not very impressive, admittedly, because you can access it through Request.UserHostAddress anyway.) More interestingly, you can use URL authorization by specify- ing the IP addresses as the usernames: <authorization> <allow users=”127.0.0.1” /> LISTING 14.1 Continued 19 0672326744 CH14 5/4/04 12:27 PM Page 541 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. <allow users=”56.43.43.1” /> <allow users=”56.43.43.2” /> <allow users=”56.43.43.3” /> <deny users=”*” /> </authorization> You could also have the IPAuthenticationModule implementation create the GenericPrincipal object with roles that reflect what sort of information should be displayed to that client. You would then be able to use Context.User.IsInRole or any of the other programmatic authorization techniques to access this information. Running Authentication Modules in Tandem The built-in authentication modules in ASP.NET can only be used one at a time, but there is no reason you cannot have additional custom authentication modules running on top of the built- in modules. For example, you might want to use forms authentication to allow administrators to sign in to the system but use the IPAuthenticationModule implementation that you built in the previous section to identify the client machine for users who are not authenticated by the forms authen- tication module. The important thing to do if you want to use more than one module together is to ensure that they do not clash with each other. You can change the IPAuthenticationModule implementation so that it will populate the Context.User object only if it has not already been populated by another authentication module (see Listing 14.2). LISTING 14.2 Adapting IPAuthenticationModule to Allow It to Work with Other Modules Public Sub Authenticate(ByVal sender As Object, ByVal e As EventArgs) Dim application As HttpApplication = CType(sender, HttpApplication) ‘check that the user has not been created or is not authenticated If application.Context.User Is Nothing _ OrElse Not application.Context.User.Identity.IsAuthenticated Then ‘create identity and principal objects Dim identity As New IPIdentity(application.Request.UserHostAddress) Dim principal As New GenericPrincipal(identity, New String() {}) ‘attach the principal to the application context application.Context.User = principal End If End Sub 14 Customizing Security 542 19 0672326744 CH14 5/4/04 12:27 PM Page 542 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 543 Building a Custom Authorization Module The IPAuthenticationModule implementation will then happily coexist with the forms authentication module. When forms authentication does not authenticate the user, the IPAuthenticationModule implementation will populate the Context.User object. When forms authentication does pick up a ticket and authenticate the user, the IPAuthenticationModule imple- mentation will do nothing. This system will work best when forms authentication is set up to support role-based authoriza- tion, so that the administrators or other privileged users can be placed in a role. The example shown here is very simple, but it shows all the features that are required from an authentication module. If you have some authentication requirements that are not served by the default modules, you should be able to build a custom module to do the job. Building a Custom Authorization Module Authorization is the process of deciding whether the current user has permission to access the resource that he or she requested. The authorization modules that ship with ASP.NET decide whether the resource can be accessed by either checking Windows access control lists (file authorization) or checking the <authorization> element of the configuration file (URL authoriza- tion). There are lots of other possibilities for authorizing the requests of users. For example, you might allow access only at certain times, you might require users to have been registered with the application for a certain amount of time before accessing some content, or you might assign each user credits that he or she can use to access pay-per-view content. Or you might use a single-page application architecture and want to authorize based on the URL parameters of the request. The best way to implement custom authorization behavior is by creating an authorization module. Like authentication modules, authorization modules are HTTP modules (although they hook into the AuthorizeRequest event rather than the AuthenticateRequest event). Listing 14.3 shows a simple authorization module that checks the expiration date in a custom identity against the current date. LISTING 14.3 A Custom Authorization Module Public Class ExpirationAuthorizationModule Implements System.Web.IHttpModule Public Sub Dispose() Implements System.Web.IHttpModule.Dispose ‘nothing to dispose of End Sub Public Sub Init(ByVal context As System.Web.HttpApplication) ➥Implements System.Web.IHttpModule.Init AddHandler context.AuthorizeRequest, AddressOf Me.Authorize 19 0672326744 CH14 5/4/04 12:27 PM Page 543 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. End Sub Private Sub Authorize(ByVal sender As Object, ByVal e As EventArgs) Dim application As HttpApplication = CType(sender, HttpApplication) If application.Context.Request.IsAuthenticated Then If Not application.Context.User.IsInRole(“NonExpiring”) Then Dim identity As ExpiringIdentity = _ CType(application.Context.User.Identity, ExpiringIdentity) If identity.Expires < DateTime.Now Then ‘the users registration has expired application.Context.Response.Redirect(“RegistrationExpired.aspx”) End If End If End If End Sub End Class The infrastructure of this authorization module is very similar to that of the custom authentica- tion module discussed earlier in this chapter in the section, “What Is an Authentication Module?” In the Authorize event handler, you check whether the user is authenticated. (This module is designed to only check for expired membership; it does not deny authorization to anonymous users. It is assumed that URL authorization would be used to do that.) Next, you check that the user is not in the NonExpiring role. If he or she is, you do nothing more, and the user is allowed to view the resource he or she requested. If the user is not in the NonExpiring role, you check the current date and time against the user’s expiration date and time from the ExpiringIdentity object in Context.User.Identitiy . If the user has expired, you redirect the response to the “registration expired” page. You may be wondering what the ExpiringIdentity class looks like. It is shown in Listing 14.4. LISTING 14.4 The ExpiringIdentity Class Public Class ExpiringIdentity Implements System.Security.Principal.IIdentity Private _Username As String Private _MembershipExpires As DateTime Public Sub New(ByVal username As String, ByVal expires As DateTime) 14 Customizing Security 544 LISTING 14.3 Continued 19 0672326744 CH14 5/4/04 12:27 PM Page 544 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 545 Building a Custom Authorization Module _Username = username _MembershipExpires = expires End Sub Private Sub New() End Sub Public ReadOnly Property AuthenticationType() As String _ Implements System.Security.Principal.IIdentity.AuthenticationType Get Return “Custom” End Get End Property Public ReadOnly Property IsAuthenticated() As Boolean _ Implements System.Security.Principal.IIdentity.IsAuthenticated Get Return True End Get End Property Public ReadOnly Property Name() As String _ Implements System.Security.Principal.IIdentity.Name Get Return _Username End Get End Property Public ReadOnly Property Expires() As DateTime Get Return _MemberShipExpires End Get End Property End Class Running Authorization Modules in Tandem As with authentication modules, you can run multiple authorization modules at the same time. You do not have to worry about clashing authorization modules as you do with authentication modules. If any of the authorization modules in the chain results in failed authorization, it will take action ahead of any other modules. This is as it should be; when it comes to security, you should always pay attention to the test that fails rather than to the test that passes. LISTING 14.4 Continued 19 0672326744 CH14 5/4/04 12:27 PM Page 545 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. The example shown in Listing 14.4 is designed to work in tandem with URL authorization. URL authorization would be used to keep anonymous users from using the application, whereas ExpirationAuthorizationModule implementation would be used to deal with users whose registra- tions have expired. Trust Levels By default, ASP.NET applications run at full trust. This means that the .NET Framework places no limitations on what they can do, aside from the limitations imposed by the operating system on the account that ASP.NET runs under. This is not a huge problem if you trust all the develop- ers who write code for all the ASP.NET applications that run on your server, but what if you do not? Also, running all applications at full trust breaks the principle of least privilege—the idea that for the best possible security, code should be allowed only the permissions that it absolutely needs. The solution is to force applications to run at less than full trust. ASP.NET ships with four differ- ent levels of trust and allows you to configure your own trust levels if you need to specify a particular set of permissions. Using One of the Preconfigured Trust Levels In addition to the full-trust mode that places no restrictions, four trust levels are provided with ASP.NET (see Table 14.1). TABLE 14.1 The Four Trust Levels Provided with ASP.NET Trust Level Main Permissions Minimal Only the bare minimum that are required for ASP.NET to function Low Very limited access to the file system Medium Limited read/write access to the file system; some other permissions High Full access to the file system; most other permissions Remember that the permissions granted by these trust levels do not allow the ASP.NET user account to access anything that it does not have operating system permissions for. Trust levels can only impose additional restrictions; they can never remove existing operating system restric- tions. Let’s look at each trust level in more detail to see what permissions the levels provide. The Minimal Preconfigured Trust Level The minimal trust level only grants the permissions that are absolutely required for an ASP.NET application to run. 14 Customizing Security 546 19 0672326744 CH14 5/4/04 12:27 PM Page 546 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 547 Trust Levels An ASP.NET application running at this trust level will not be able to do a lot. It can’t do any file system input/output work, can’t do any data access, can’t access isolated storage, can’t access the registry, and can’t execute any code that requires reflection. In fact, applications at this trust level can’t really do anything apart from read the HTTP request and write to the HTTP response. Another restriction when running at this trust level (and low trust) is that it does not allow debugging. Attempting to run an application that is configured for debugging at this trust level will result in an error message. For this reason, you have to appropriately set the <compilation> element in the web.config file for applications that will run at minimal or low trust: <compilation defaultLanguage=”vb” debug=”false” /> The Low Preconfigured Trust Level The low trust level does not allow very many more permissions than minimal trust. At this level, the application can read (but not write) files that are within its application directory, and it can read and write isolated storage with a quota of 1MB. Note that the low trust level has the same limitation on debugging that the minimal trust level has: If you configure an application with low trust for debugging, you will get an error. The Medium Preconfigured Trust Level Compared to the minimal and low trust levels, quite a few additional permissions are added at the medium trust level. Debugging is now allowed. You can read and write files within the application directory. You also have access to isolated storage with an effectively unlimited quota. An application can access a SQL Server database through the SqlClient classes and can even print to the default printer. At this level, an application also gets read access to the following environment variables: n TEMP n TMP n USERNAME n OS n COMPUTERNAME Finally, at medium trust, an application gets more control over threads, the principal object, and remoting. The medium trust level contains the permissions that most ASP.NET applications need to run. The High Preconfigured Trust Level At high trust, an application gets unrestricted access to most resources, including the file system, isolated storage, environment variables, the registry, and sockets. An application also gains the ability to generate dynamic assemblies by using Reflection.Emit . 19 0672326744 CH14 5/4/04 12:27 PM Page 547 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... all applications in the InsiderSolutions folder as follows: Creating Custom Trust Levels The trust levels that ship with ASP.NET provide a pretty... of the Web server (usually wwwroot), specify that the application called UntrustedApp that is in the InsiderSolutions folder should be run at low trust: ...548 14 Customizing Security Remember, though, that ASP.NET is still limited by the permissions that the account under which it runs has been given Forcing an Application to Use a Trust Level As mentioned earlier in this chapter, the default trust level for ASP.NET applications is full trust You can see this by finding the appropriate section of the machine.config... to the permission set that it should run with For the purposes of changing the permissions that ASP.NET applications run with, you do not need to change the elements; you just need to add or remove permissions from the element that holds the permissions that are granted to the ASP.NET application The Web_MediumTrust.config file contains three permission sets: a full access... Trust Levels Listing 14.5 shows the element from Web_MediumTrust.config that is granted to the code of the ASP.NET application itself LISTING 14.5 Permissions from the Medium Trust Level Configuration File The permission set named ASP.NET is assigned to the code of the application in all the trust level files It is quite easy to read the various permissions from the file, to see what the application will be allowed to do Removing... PublicKeyToken=b77a5c561934e089”/> Trust Levels Fortunately, there is a way to generate the elements you need—by using the NET Framework Configuration tool The tool does not allow you to edit the ASP.Net trust level policy files directly, but you can add permissions to a permission set in one of the files that the tool can edit and then copy them across to the trust level file To use the NET Framework... this permission set for anything) It would be best to give it a name and description that make it clear that this is a temporary set that you are using to create permissions and classes to copy across to ASP.NET configuration Then you can click Next, and you will see the window where you can add permissions to the set (see Figure 14.2) FIGURE 14.2 Adding permissions to a permission set 553 554 14 Customizing... runtime You can also use the following substitutions: $OriginHost$ - the address of the client that made a request to the application $AppDirUrl$ - the URL of the application $CodeGen$ - The folder where ASP.NET stores dynamically generated assemblies $Gac$ - the Global Assembly Cache folder Note that the last three substitutions are usually used in code groups rather than in permissions 555 556 14 Customizing . usernames: <authorization> <allow users= 12 7.0.0 .1 /> LISTING 14 .1 Continued 19 0672326744 CH14 5/4/04 12 :27 PM Page 5 41 Please purchase PDF Split-Merge on. restrictions, four trust levels are provided with ASP. NET (see Table 14 .1) . TABLE 14 .1 The Four Trust Levels Provided with ASP. NET Trust Level Main Permissions Minimal

Ngày đăng: 21/01/2014, 09:20