Professional ASP.NET 2.0 Security, Membership, and Role Management phần 9 pps

64 445 0
Professional ASP.NET 2.0 Security, Membership, and Role Management phần 9 pps

Đ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

With this configuration, the provider expects that any usernames passed to its methods will be just the username portion of the NT4-style DOMAIN\USERNAME format. For example, the following code retrieves the user object for CORSAIR\demouser: MembershipUser mu = Membership.GetUser(“demouser”); Notice how the username parameter doesn’t include the domain identifier. This is important because if you attempt to pass full NT4-style usernames to the provider, the calls will never return anything (that is, if you pass DOMAIN\USERNAME the provider is literally looking for a user object whose SAM account name is DOMAIN\USERNAME ). Because the provider already knows the domain within which it is operat- ing, it does not need the domain portion of the username. Remember that the provider is effectively acting like a database provider— except that the “database” is really an LDAP server. When the provider looks for objects using a SAM account name, it is performing an LDAP search where the sAMAccountName attribute on the directory’s user object equals a specific value. As a result, you only need to supply the username. If you happen to set up ActiveDirectoryMembershipProvider, and you are unable to retrieve any existing users, keep in mind the attributeMapUsername attribute. It is likely that if the connection string works and you are getting back nulls from methods like GetUser that your directory users have been configured only with SAM account names— and not UPNs. Switching attributeMapUsername over to sAMAccountName is probably the most common configuration step that developers need to make to get the provider working with their directory. However, if you have been creating user accounts in the directory using the ActiveDirectoryMembershipProvider with its default setting of UPN-style usernames, you may run into a different problem. When you create users in the Active Directory Users and Computers MMC, the UI conveniently auto-selects a domain suffix for your UPN. In fact, the UI remembers previous UPN suffixes that have been used with the tool, and it displays a drop-down list where you can choose any one of them. However, if you create users directly with the provider, you may find yourself creating users with just a username and no suffix (for example, “demouser98” as opposed to “demouser98@corsair.com”). This kind of a UPN will sort of work with Active Directory, but you will find that if you also write code with System.DirectoryServices there are cases where a UPN without an @ will fail. As a result, you should always ensure that UPNs have an @ sign and some kind of domain suffix in them. For Internet-facing sites, it makes sense to create user accounts with some kind of domain suffix — with the user’s email address being the most likely candidate. This raises the question of whether you should eventually switch your user population over to UPNs. Although as far back as Windows 2000, the guidance was to create users with UPNs, the reality is that many folks still rely on the older NT4-style usernames, especially if their current domain infrastructure was the result of an NT4 domain upgrade. I certainly wouldn’t recommend reworking your user popu- lation to use UPNs just because ActiveDirectoryMembershipProvider defaults to UPNs. (That’s why the username mapping is configurable!) However, it does seem to be a recurring theme that UPNs are architecturally preferable. For e-commerce sites or extranet sites that rely on Active Directory, UPNs do make more sense because, typically, you don’t want external users to be aware of AD domain names. Technically, external sites that do this are leaking a little bit of their security architecture to the public by requiring a domain name. Also UPNs frequently mirror a person’s email address, so they can be a more natural username for your website users to grasp. 485 ActiveDirectoryMembershipProvider 15_596985 ch12.qxp 12/14/05 7:52 PM Page 485 Container Nesting You already saw a simple example where nested OUs were used in a connection string. However, con- tainer nesting raises some interesting issues when working with the provider. If you have different sets of users in different OUs, and you want some provider operations to span all of these sets of users, how do you go about configuring the provider? Remember that data modification operations can occur only in the container specified by the connection string, whereas search-oriented operations are rooted at the container specified by the connection string. Using the sample directory structure, so far there are users are laid out as follows: Cn=Users demouser OU=UserPopulation_A testuserpopA OU=SomeNestedOU Testusernestedinpopa If you use the following connection string: <add name=”DirectoryConnection” connectionString=”LDAP://corsdc2.corsair.com”/> then all search operations are rooted at what is called the default naming context for the domain. What this means is that all containers and OUs are considered children of the default naming context, so this type of connection string allows searches to be performed across all available containers. Because the provider performs its search operations using subtree searches, the following code searches across all containers, as well as down through the container hierarchy to its lowest nested level: MembershipUserCollection muc = Membership.GetAllUsers(); foreach (MembershipUser mu in muc) Response.Write(“Username: “ + mu.UserName + “<br />”); The result from running this code is: Username: appimpersonation@corsair.com Username: demoadmin@corsair.com Username: demouser@corsair.com Username: fradmin@corsair.com Username: testusernestedinpopa@corsair.com Username: testuserpopa@corsair.com Username: uncidentity@corsair.com The bolded identities are the three accounts used earlier in the chapter. The demouser account as well as all of the other unbolded user accounts are located in the CN=Users container (some of the accounts should be a bit familiar from back in Chapters 1 and 2!). The other two testuser* accounts are from OU=UserPopulation_A and OU=SomeNestedOU. 486 Chapter 12 15_596985 ch12.qxp 12/14/05 7:52 PM Page 486 Similarly, if you perform get operations such as: MembershipUser mu = Membership.GetUser(“testusernestedinpopa@corsair.com”); the code will return a valid user object because even though the user account is nested two OUs deep, the Get* methods on the provider start their search at the default naming context (because the connec- tion string from earlier doesn’t specify a container) and then work their way down. If you explicitly specify a container hierarchy in your connection string, then get and search methods will be rooted at the container you specify and then searches will work their way down through any remaining container hierarchy. However, if you attempt to create a new user or delete an existing user, then these operations only occur in the container specified on the connection string. In the case of the sample connection string that doesn’t explicitly specify a container, this means that user creation and deletion only occur in the CN=Users container. There are other provider methods that involve modifying information for a user, including UpdateUser, ChangePassword, and so on. Although these methods are technically data-modi- fication operations, all of these methods first bind to a specific user in the directory (a get operation) prior to making a change. As a result, updates to existing users also have the behavior of being rooted at a spe- cific point in the directory, and then searching for the user object down through the nested containers. With this behavior, it is possible to come up with some interesting provider configurations. For example, if your site supports multiple sets of users, you could allocate each set of users to a different OU. You could then configure a separate provider instance for each different OU (and hence each provider instance would have its own unique connection string). These different providers could be used exclu- sively for create and delete operations. For the rest of your site, you could then configure one more provider pointed at the default naming context or at a root OU, depending on how you structured your containers. This last provider would be used for things like calling ValidateUser or for fetching a MembershipUser object to display information on a page. In this way, you would get the flexibility to create and delete users in different OUs, while still having the convenience of searching, retrieving, and modifying users across the OUs with a single provider. Securing Containers So far, the sample code has been running with the credentials of the IIS6 worker process. The reason that the samples have worked so far is that the NETWORK SERVICE account is implicitly considered part of the Authenticated Users group. If you look at the default security configuration in the directory, you will see that this group has rights to list objects in a container as well as having some read permissions on individual object. The concept of read permissions on objects though differs depending on the object in question. In the case of the provider, the object type you care about are user objects. The default permissions that any authenticated user in a domain has on any other user object in the directory are read general information, read personal information, read web information, and read public information. General information, per- sonal information, web information, and public information are just property sets that conveniently group together dozens of different directory attributes so that permissions can be granted to them without having to spam dozens or hundreds of ACLs on user objects. These default permissions are why the sample pages running as NETWORK SERVICE were able to find the user object in the first place and then read the vari- ous directory attributes in order to construct an instance of ActiveDirectoryMembershipUser. 487 ActiveDirectoryMembershipProvider 15_596985 ch12.qxp 12/14/05 7:52 PM Page 487 If you attempt to use the sample configuration shown earlier to update an existing user object or create a new user object, you will get a System.UnauthorizedAccessException. The exception bubbles up from the underlying System.DirectoryServices API and is triggered because, for obvious reasons, authenticated domain users don’t have the right to arbitrarily make data modifications to other objects or containers in the directory. This behavior is roughly equivalent to the exceptions you get when you haven’t granted login rights to SQL Server or execute permissions to the Membership stored procedures and you attempt to use the SqlMembershipProvider. One obvious solution would be to just add rights in the directory granting NETWORK SERVICE the required rights. However, in general this is not the correct approach. Each machine in a domain has a corresponding machine account in the directory. Because the account is comparatively well known, granting broad rights to it is not something you should do. Additionally, if you are running in a web farm, each individual server has a different machine account in the directory that locally is known as NETWORK SERVICE. So if you granted broad rights to the machine account, you would have to repeat this task for each and every server running in your web farm. A better approach would be to at least assign your application’s worker process a different domain iden- tity and then grant this domain identity the necessary rights in the directory depending on what your code needs to do with the provider. With this approach, if you run multiple machines in a web farm, each web server can be configured with the same domain account for the worker process. For a lot of application scenarios, this is actually a reasonable approach. However, if you need to host multiple applications in a single worker process, with each application having a different set of privileges in the directory, or if you want to configure multiple providers in a single application with each provider hav- ing a different set of privileges, then you will need to use explicit provider credentials instead. The ActiveDirectoryMembershipProvider exposes the connectionUsername and connectionPassword configuration attributes. With these attributes, you can explicitly set the domain credentials that the provider will use when connecting to the directory. Even though the default provider behavior is to revert to either the process credentials, or application impersonation credentials if application impersonation is being used, when explicit credentials are configured the provider always uses them in lieu of any other security identity. The advantage of using explicit credentials in combination with application specific OUs (as opposed to just using the Users container) is that you have the ability to specify granular permissions for different sets of application users. With the provider configuration attributes you then have the flexibility to fine-tune individual providers to allow only certain operations through specific providers. Let’s see how this works by creating a new admin account to work with the UserPopulation_A container: userpopaadmin. You want this account to have the ability to create and delete user objects, as well as the ability to reset pass- words and unlock users. Remember that for a provider instance to be able to create users, it also needs the ability to delete users (in the event that the multistep user creation process failed) and to set passwords (because part of the process of creating the user is setting password). Note that the ability to set passwords for new accounts as well as reset existing passwords is shown as the Reset Password inside of the security dialogs boxes shown in the MMC. 488 Chapter 12 15_596985 ch12.qxp 12/14/05 7:52 PM Page 488 The Active Directory Users and Computers MMC has a wizard that steps you through delegating control over containers like the OUs used here. You can open up the MMC to display all of the containers that are currently available in a directory. In the test directory, I am running, right-clicking the UserPopulate_ A container and selecting Delegate Control opens the first step of the wizard as shown in Figure 12-1. In the next wizard step you can select one or more user/group accounts that will all be granted a specific set of rights over the OU. In Figure 12-2, you can see that I have selected the userpopaadmin account. Figure 12-1 489 ActiveDirectoryMembershipProvider 15_596985 ch12.qxp 12/14/05 7:52 PM Page 489 Figure 12-2 On the next step of the wizard, you can select multiple rights to grant to the accounts. Because you want the admin account to have the ability to create/delete users, reset passwords and unlock users, the first three sets of tasks are selected in the wizard. Figure 12-3 shows these selections. 490 Chapter 12 15_596985 ch12.qxp 12/14/05 7:52 PM Page 490 Figure 12-3 The final step of the wizard (not shown) just asks for confirmation of the selections. When you click the Finish button on the last wizard step, the security changes take effect. You can see the new set of security rights if you right-click the UserPopulation_A OU and then drill into the security settings for user- popaadmin. Figure 12-4 shows the two sets of rights highlighted in the Advanced Security Settings dialog box. 491 ActiveDirectoryMembershipProvider 15_596985 ch12.qxp 12/14/05 7:52 PM Page 491 Figure 12-4 Notice that the account now has Full Control on any user objects in the container as well as the Create/ Delete User Objects privilege on the container. The account needs to have two different sets of rights because the intent is for the userpopaadmin account to have a set of specific user object rights within the container as well as the ability to add and remove user objects in the container. Notice that the account doesn’t have Full Control on the container itself. This allows other object types that are managed by other user accounts to be stored in the container. If you highlight the Full Control row and click the Edit button, you will see the set of permissions that userpopaadmin now has on any user object located in the container. Specifically, it has Write All Properties permission as well as the Reset Password and Change Password permissions. These permis- sions will allow userpopaadmin the ability to set all of the properties on a newly created user object (including the password property) as well as the ability to reset the password when the ResetPassword method is called on the provider. These permissions also allow the account to be used when calling the Update method because this method updates a number of different properties on a user object in the directory. With the security configuration for the admin user complete, you can make use of it to connect to the directory with a connection string which points directly at the OU: 492 Chapter 12 15_596985 ch12.qxp 12/14/05 7:52 PM Page 492 <add name=”DirectoryConnection” connectionString=”LDAP://corsdc2.corsair.com/ OU=UserPopulation_A,DC=corsair,DC=com”/> In this example, you configure two providers: one for admin operations and one for get/search operations: <membership defaultProvider=”readonlyprovider”> <providers> <clear/> <add name=”adminprovider” type=”System.Web.Security.ActiveDirectoryMembershipProvider, ” enableSearchMethods=”true” connectionUsername=”userpopaadmin@corsair.com” connectionPassword=”pass!word1” connectionStringName=”DirectoryConnection” /> <add name=”readonlyprovider” type=”System.Web.Security.ActiveDirectoryMembershipProvider, ” enableSearchMethods=”true” connectionStringName=”DirectoryConnection” /> </providers> </membership> The provider named adminprovider uses the explicit credentials with elevated privileges. The second provider instance named readonlyprovider depends on the default rights that the Authenticated Users group has to read various attributes on a user object. Note that in a production environment you should use protected configuration (discussed in Chapter 4) so that the explicit credentials are not stored as cleartext. You can now create users with the admin provider: MembershipCreateStatus status; MembershipProvider mp = Membership.Providers[“adminprovider”]; mp.CreateUser(“demouser103@nowhere.org”, “pass!word1”, “demouser103@nowhere.org”, null, null, true,null, out status); Response.Write(status.ToString()); Read operations use the default provider running as NETWORK SERVICE, and thus the default provider can only search for users and read attributes on the user object. Note that you can take security lock down a step further by removing the Authenticated Users ACL from the default ACL defined for the user class in the directory’s schema. Doing so gets into the nitty-gritty of managing Active Directory default ACLs, which is a bit far afield from the topic of how to use ActiveDirectoryMembershipProvider. However, if you have changed the default ACL for the user object (you can see the default ACL using the Active Directory Schema editor, look at the Default Security tab on the Properties dialog box of the user class) by removing the Authenticated Users group, you can create a read-only user account using the same approach just shown for the administrative user. Just create a new read-only user account and with the Delegation of Control Wizard grant read permissions on all user objects in the container to the account. Because the wizard will end up granting read permissions on all attributes of user objects, you can right-click the container and use the Security tab to fine-tune the specific sets of user attributes that you really want the read-only account to have access to. The default set of permissions granted to the Authenticated Users account as described earlier is a good starting point. 493 ActiveDirectoryMembershipProvider 15_596985 ch12.qxp 12/14/05 7:52 PM Page 493 Configuring Self-Service Password Reset Self-service password resets are the one piece of provider functionality that is not “auto-magically” sup- ported without a moderate amount of intervention on your part. Unlike SqlMembershipProvider, where this functionality is just a matter of setting the enablePasswordReset configuration attribute to true, ActiveDirectoryMembershipProvider requires schema changes prior to turning on the func- tionality. Furthermore, after the schema changes are made you need to configure the ACLs appropriately in the directory so that a provider has rights to read and update these properties. You could use preexisting directory attributes to store password question-and-answer-related informa- tion. Although this saves you from having to modify the directory schema, from a long-term perspective it makes more sense to extend the schema with attributes to support the provider, rather than attempt to reuse existing directory attributes. This will prevent problems down the road if you overloaded a direc- tory attribute for use with the provider, but then find out you actually need to “take back” the attribute for its original purposes. The attributes that you need to add are those for the following pieces of information: ❑ Password question — A Unicode string attribute to store the user’s password question. ❑ Password answer — A Unicode string attribute to store the user’s password answer. ❑ Failed password answer count — An attribute of type Integer that is the counter for keeping track of the number of failed password answer attempts. ❑ Failed password answer time — An attribute of type Large Integer/Interval that will store the beginning of the time tracking window for failed password answer attempts. ❑ Failed password answer lockout time — An attribute of type Large Integer/Interval that stores the time the account was locked out because of too many failed password answer attempts. You can use the Active Directory Schema snap-in to create five new attributes for storing these values. Before you do so, note that you have to have rights to edit the schema for your domain. This right is nor- mally reserved for members of the Schema Admins group because of the sensitive nature of schema edits. Schema edits are a one-way affair; after you add an attribute, you can never actually delete it. Instead, you can only deactivate attributes. For this reason, enabling self-service password reset for the provider makes sense only for Internet facing websites that rely on Active Directory. Making irreversible schema edits to an extranet directory is less of an issue than making schema edits to your core corporate directories. Whenever you create a new directory attribute you need to have a name for the attribute as well as an X.500 OID. If you are an old database developer like me, the need for the OID is sort of weird, but it is a necessary part of creating any new classes or attributes in Active Directory. If you happen to have the Windows 2000 Resource Kit lying around it has a handy command-line tool called oidgen.exe that will automatically generate a base OID for new attributes. I created five new attributes in my directory as follows: 494 Chapter 12 15_596985 ch12.qxp 12/14/05 7:52 PM Page 494 [...]... applicationspecific role information using the Role Manager feature 5 19 Chapter 13 The interaction between Roles and RolePrincipal is described here for each of the relevant façade methods: ❑ IsUserInRole — If the current user is a RolePrincipal, and the username parameter to this method matches the username (that is, IIdentity.Name) for the RolePrincipal, and the name of the provider associated with this RolePrincipal... authenticated users and role information across different client applications This chapter will cover: ❑ The Role class ❑ The RolePrincipal class ❑ The RoleManager model ❑ RoleProvider ❑ WindowsTokenRoleProvider The Roles Class As with the Membership feature, the Role Manager feature has a static class that can be used as an easy way to access the functionality of the feature The Roles class has methods and properties... user hits your site the RoleManagerModule will automatically call DeleteCookie One thing that developers sometimes look for when they start working with the Role Manager feature and the Roles class is some kind of role object For ASP.NET 2.0, a role is just a string value — there is no rich object model for representing a role or manipulating a role As a result, when you use the Roles class, you can see... provider inside of a GAC’d assembly 516 Role Manager Role Manager is a new feature in ASP.NET 2.0 that provides the basic functionality necessary to create an IPrincipal-based object associated with roles The motivation for the Role Manager feature is to make it easy for developers to associate users with roles and then perform role checks both declaratively and in code The Role Manager feature is sometimes... matches, then the Roles class calls RolePrincipal.GetRoles Otherwise, the Roles class calls the GetRolesForUser method on the default provider ❑ DeleteRole — This method checks to see whether the current user is a RolePrincipal and if the RolePrincipal object uses the default provider If both of these conditions are met, and if the RolePrincipal instance has cached role information within itself, the... IsUserInRole overload, the username is taken from HttpContext.Current.User So if a RolePrincipal is attached to the context for this case, the parameterless IsUserInRole overload usually results in a call to RolePrincipal.IsInRole instead ❑ GetRolesForUser — This method has the same behavior as IsUserInRole If the current user is a RolePrincipal, and all of the other data matches, then the Roles class... decryptionKey=”A225 194 E99BCCB0F6B92BC9D82F12C 290 7BD07CF069BC8B4” decryption=”AES” /> With the changes to the admin provider and the definition of a fixed decryption key, the sample application can now create users with question and answers Because the Login controls work seamlessly with arbitrary membership providers, I just dropped a CreateUserWizard onto a form, configured it to use the admin provider, and started... the principal belongs to the role that is being deleted If this is the case, the method invalidates the RolePrincipal cache by calling RolePrincipal SetDirty Normally, you see this behavior only if you are in a management application and you change the role membership for the user that you are currently logged in as ❑ AddUserToRole, AddUsersToRoles, AddUserToRoles, AddUsersToRole — All of these methods... CacheRolesInCookie — By default, this value is set to false If it is set to true, the RoleManagerModule attempts to improve the performance of the Role Manager feature by caching the roles for a user within a cookie and using the cookie during subsequent page hits Cookie caching is covered in detail in the section on the RoleManagerModule ❑ MaxCachedResults — The maximum number of roles that the RoleManagerModule... user is represented by a RolePrincipal, and the method calls on the Roles class potentially affects that user This allows the Roles class to take advantage of the caching behavior in the RolePrincipal class For web applications, the current user is determined by looking at HttpContext.Current.User Because the Role Manager feature is also supported for non -ASP.NET applications, the Roles class will look . 1 .2. 8 40. 113556.1.4. 700 0 .23 3 .28 688 .28 684.8 .311583. 60 825 .551176.463 623 .1 ampPasswordAnswer 1 .2. 8 40. 113556.1.4. 700 0 .23 3 .28 688 .28 684.8 .311583. 60 825 .551176.463 623 .2 ampFailedPasswordAnswerCount 1 .2. 8 40. 113556.1.4. 700 0 .23 3 .28 688 .28 684.8 .311583. 60 825 .551176.463 623 .3 ampFailedPasswordAnswerTime. 1 .2. 8 40. 113556.1.4. 700 0 .23 3 .28 688 .28 684.8 .311583. 60 825 .551176.463 623 .3 ampFailedPasswordAnswerTime 1 .2. 8 40. 113556.1.4. 700 0 .23 3 .28 688 .28 684.8 .311583. 60 825 .551176.463 623 .4 ampFailedPasswordAnswerLockoutTime 1 .2. 8 40. 113556.1.4. 700 0 .23 3 .28 688 .28 684.8 .311583. 60 825 .551176.463 623 .5 You can. follows: 494 Chapter 12 15_ 596 985 ch 12. qxp 12/ 14 /05 7: 52 PM Page 494 Attribute Name (Both LDAP and Common) OID ampPasswordQuestion 1 .2. 8 40. 113556.1.4. 700 0 .23 3 .28 688 .28 684.8 .311583. 60 825 .551176.463 623 .1 ampPasswordAnswer

Ngày đăng: 12/08/2014, 23:22

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan