The function of a membership provider is to interface with a data store that contains data regarding a site's registered users and to provide methods for creating and deleting users, verifying login credentials, changing passwords, and more. Within the ASP.NET 2.0 framework System.Web.Security namespace is a MembershipUser class that defines the basic attributes of a membership user. Table 9-2 shows the methods and properties required by DotNetNuke to implement a custom membership provider. If you compare this table to the Member Role table on Microsoft's site, you'll notice they are very similar.
Method/Property | Description |
---|---|
MinPasswordLength | Minimum length each password must be. |
MinNonAlphanumericCharacters | Number of non-alphanumeric characters required in a user's password. |
PasswordFormat | How the passwords are stored in the data store. The options are Clear, Hashed , or Encrypted. |
PasswordStrengthRegularExpression | A regular expression each password is passed through to verify it meets additional criteria. |
RequiresQuestionAndAnswer | Determines if users are required to have a question and answer for accessing their password. |
ChangePassword | Changes a user's password. |
ChangePasswordQuestionAndAnswer | Changes a user's password question and answer. |
CreateUser | Creates a single user. |
DeleteUser | Deletes a single user. |
GetPassword | Returns the password of a user. |
GetUser | Returns a single user. |
GetUserByUserName | Returns a single user by their username. |
GetUserMembership | Returns all the membership-specific information for a single user. |
GetUsers | Returns a list of users. |
GetUsersByEmail | Returns a list of users by e-mail address. |
GetUsersByUserName | Returns a list of users by username. |
GetUsersByProfileProperty | Returns a list of users who meet criteria by various profile properties. |
ResetPassword | Resets a user's password. |
UnLockUser | Unlocks a user account so they can login to the portal. |
UpdateUser | Updates a single user. |
UserLogin | Authenticates a single user. |
All methods listed in the table that return more than a single row of records are set up to use record paging. All the properties listed in Table 9-2 are retrieved from the web.config file. Listing 9-2 shows the set of properties for the default AspNet membership provider. This is contained in the memberrolesprototype section of the web.config file. Although this listing is specific to the default AspNet concrete provider, having a value set for each of these for any concrete membership provider is required by the abstract provider within DotNetNuke.
Listing 9-2: Membership Provider Set in web.config
<membership userIsOnlineTimeWindow="15"> <providers> <add name="DNNSQLMembershipProvider" type="DotNetNuke.Security. Membership.AspNetSqlMembershipProvider, DotNetNuke. Provider.AspNetProvider" connectionStringName="SiteSqlServer" enablePasswordRetrieval=" true" enablePasswordReset="true" requiresQuestionAndAnswer="false" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" requiresUniqueEmail="false" passwordFormat=" Encrypted" applicationName="/" description="Stores and retrieves membership data from the local Microsoft SQL Server database" /> </providers> </membership>
One of the properties in this listing is passwordFormat. By default, its value is set to Encrypted. The value uses the machinekey property, which is also set and stored in the web.config file as shown in Listing 9-3. This node is located within the system.web node in that file.
Listing 9-3: MachineKey Values Set in web.config
<add key="MachineValidationKey" value= "C505D402B1EC5185E5447F2F5DFD16263715D6D3" /> <add key="MachineDecryptionKey" value= " 28F7B5984BAF6B7706B6E63FAB0481B713818EAA0F12E033" /> <add key="MachineValidationMode" value="SHA1" />
At installation, the validationKey and the decryptionKey are regenerated and replaced with a custom value unique to your install. Because this is what encrypts your passwords, you must be very careful to safeguard the values assigned during DotNetNuke installation. If these values are altered by someone or the entire file is overwritten, no passwords will match for any of the users who registered while the application used the old key. If none of the passwords match, nobody can log in to your install. This could become an even bigger problem if the values are changed and additional users are registered using the newest keys. You would have the previous registered users having passwords encrypted using the old key and the new users' passwords encrypted using the new key. The key set you decide to use results in one set of your users not being able to log in.
Important | To avoid possible future catastrophe, it is critical to back up these keys after they are set by the DotNetnuke installation. It's also recommended that you keep a backup copy of the web.config file in a safe place just in case it is accidentally overwritten. |
Listing 9-4 shows the CreateUser method from the AspNet concrete provider code located in the AspNetMembershipProvider.vb file.
Listing 9-4: CreateUser Method in the Concrete AspNet Membership Provider
Public Overrides Function CreateUser(ByRef user As UserInfo) As UserCreateStatus Dim createStatus As UserCreateStatus Try ' check if username exists in database for any portal Dim objVerifyUser As UserInfo = GetUserByUserName(Null. NullInteger, user.Membership.Username, False, False) If Not objVerifyUser Is Nothing Then If objVerifyUser.IsSuperUser Then ' the username belongs to an existing super user createStatus = UserCreateStatus.UserAlreadyRegistered Else ' the username exists so we should now verify the password If ValidateUser(objVerifyUser.PortalID, user. Membership.Username, user.Membership.Password) Then ' check if user exists for the portal specified objVerifyUser = GetUserByUserName(user.PortalID, user.Membership.Username, False, False) If Not objVerifyUser Is Nothing Then ' the user is already registered for this portal createStatus = UserCreateStatus.UserAlreadyRegistered Else ' the user does not exist in this portal - add them createStatus = UserCreateStatus.AddUser End If Else ' not the same person - prevent registration createStatus = UserCreateStatus.UsernameAlreadyExists End If End If Else ' the user does not exist createStatus = UserRegistrationStatus.AddUser End If If createStatus = UserRegistrationStatus.AddUser Then createStatus = CreateMemberhipUser(user) If createStatus = UserCreateStatus.Success Then 'Create the DNN User Record createStatus = CreateDNNUser(user) If createStatus = UserCreateStatus.Success Then 'Persist the Profile to the Data Store ProfileController.UpdateUserProfile(user) End If End If End If Catch exc As Exception ' an unexpected error occurred 'LogException(exc) createStatus = UserCreateStatus.UnexpectedError End Try Return createStatus End Function
The method first calls the GetUserByUserName function, necessary in any custom concrete provider, to see if the username is used and return the user object if it is. If no result is returned, the CreateStatus variable is set to AddUser. If a result is returned, however, a series of steps is required to see how this should be handled:
A check is done to see if the username is a SuperUser's:
If so, the CreateStatus variable is set to AlreadyRegistered.
If not, the PortalID, username, and password are passed to the private ValidateUser function.
ValidateUser looks to the data store to determine if a matching username/password combination is found for this application and returns the result:
If the result of the function is false, the CreateStatus variable is set to UsernameAlreadyExists.
If the result is true, a check is done to see if the user exists for the specific portal by calling the function GetUserByUserName.
Where no result is returned from ValidateUser, the CreateStatus variable is set to AddUser because the user does not exist for this specific portal. When a result is returned from ValidateUser, CreateStatus is set to UserAlreadyRegistered.
With the CreateStatus variable set, the required information is populated and the create user process can proceed. Finally, the CreateStatus variable is compared to the available CreateStatus options exposed by the UserCreateStatus enumerator and the proper action is taken. The UserCreateStatus enumerator is defined within the core in the file UserCreateStatus.vb. You can find this file and the others required to construct the abstract provider in $AppRoot\Library\Components\Users\Membership\.
Now you know how the abstract membership provider uses web.config to determine what concrete provider is needed for an install of DotNetNuke to run, and how additional properties needed by the provider to function properly can be retrieved from web.config. This adds flexibility for developers and those who implement DotNetNuke because they can easily change how they want their install to function without requiring them to write a single line of code.