One of the best features added in ASP. NET 2.0 is the new membership service, which provides easy-to-use APIs for creating and managing user accounts. ASP. NET 1.x introduces form authentication on a large scale, but requires you to write a considerable amount of code to perform form authentication in actual operations. The membership service fills in the shortcomings of the ASP. Net 1.x form authentication service and makes it much easier to implement form authentication.
The membership API is made public through two new classes: Membership and membershipuser. The former includes static methods for creating users, verifying users, and completing other work. Membershipuser represents a single user. It contains methods and attributes used to retrieve and change passwords, obtain the last logon date, and complete similar work. With these two new classes, we can easily manage users without writing a line of code. However, in the actual development process, it cannot meet our daily development needs. After daily project development and online data search, we will list them one by one:
1. By default, all types of databases use SQL Express. In actual development, we often use SQL Sever 2000 or SQL Server 2005. In this case, we need to modify the database type.
Microsoft provides us with an aspnet_regsql command to modify the default database. Open the Visual Studio 2005 command prompt, enter aspnet_regsql, and follow the prompts to proceed step by step.
When you open the database, you can find a series of stored procedures starting with "ASPnet _" in multiple places. This is the stored procedure necessary for using membership.
Open IIS, [properties] → [ASP. NET] → [edit configuration]:
[General], the connection parameter localsqlserver follows the normal SQL connection string format.
[Authentication], the mode is forms, and the minrequirednonalphanumericcharacters of the management provider is 0. In this case, you can remove the default abnormal password that requires a combination of letters and numbers. In this step, you can also change the minimum length and maximum length of the password.
After this step, the system automatically configures the required rules in Web. config. You can use this graphical tool to modify web. config.
2. the built-in login control and membership class only provide simple user information input, which cannot meet the needs of our project. For example, you must enter a QQ number, phone number, and home address when registering a user. By default, there is no solution. Here are two solutions. I used them in different projects. You can determine the advantages and disadvantages.
1. Use profile. There are already many online tutorials on this method. I will not repeat the description to avoid the suspicion of making a draft fee :). Here is only a description that is not provided on the Internet.
Because membership can only list the user names of a specified group, but cannot list other details, we often need to modify other information in the group at the same time in actual use. I use a self-built datatable method. See the Code:
Public static datatable listuser (string userroles) // lists the user information of a specified group.
{
String [] users = roles. getusersinrole (userroles );
// List users in a specified group
Datatable dt = new datatable ();
DT. Columns. Add ("username", system. type. GetType ("system. String "));
DT. Columns. Add ("QQ", system. type. GetType ("system. String "));
DT. Columns. Add ("phone", system. type. GetType ("system. String "));
DT. Columns. Add ("Address", system. type. GetType ("system. String "));
DT. Columns. Add ("email", system. type. GetType ("system. String "));
// Construct a data table
Foreach (string I in Users)
{
Datarow DR = DT. newrow ();
Membershipuser mu = membership. getuser (I );
Obtain basic user information
Profilecommon P = profile. getprofile (I); // obtain the user's profile information
Dr [0] = mu. Username;
Dr [1] = P. QQ;
// The profile is strongly typed and can be easily added through perception.
Dr [2] = P. Phone;
Dr [3] = P. address;
Dr [4] = mu. Email;
DT. Rows. Add (DR );
DT. acceptchanges ();
}
Return DT;
}
Public static void deleteuser (string username)/delete a specified user
{
Membership. deleteuser (username );
// The system automatically deletes the specified user information under the profile.
}
Public static void updateuser (string username)/update a specified user
{
Profilecommon P = profile. getprofile (I );
// Obtain the user's profile information
P. Phone = "phone ";
P. Address = "address;
P. QQ = "QQ number ";
P. Save ();
// Save the modification.
}
2. Customize a membershipinfo table and associate it with the membership system logo. Write your own SQL statements for query, modification, and other functions.
List users in a specified group
Select * From aspnet_membership inner join aspnet_users on
Aspnet_membership.userid = aspnet_users.userid left join memberinfo on aspnet_membership.userid = memberinfo. userid
Where aspnet_membership.userid = (select userid from aspnet_usersinroles inner join
Aspnet_roles on aspnet_usersinroles.roleid = aspnet_roles.roleid where rolename = 'admin ')
Deletion, modification, and other functions are relatively simple and will not be described here. You can use the createuser method of membership and then use SQL statements to write data to the memberinfo table.
To create a user, we can extend the createuserwizard control or write the logon interface on our own.
1. Extend the createuserwizard control. You can use its template column. Note the following: User Name, password, question, answer, email, their IDs must be username, password, question, answer, and email. Otherwise, an error occurs and the verification control cannot be used at this time. Suspected to be a bug in IDE.
As shown below, the defined style should be:
<Wizardsteps>
<Asp: createuserwizardstep runat = "server"> Custom Code <contenttemplate>
</Contenttemplate>
</ASP: createuserwizardstep>
</Wizardsteps>
Code Section:
Protected void createuserwizardinclucreateduser (Object sender, eventargs E)
{
// Because the system will automatically create basic information tables for you, you only need to modify the profile or membershipinfo mark.
Roles. addusertorole (createuserwizard1.username, "Shop ");
// Add a user to the corresponding group
Profilecommon P = (profilecommon) profilecommon. Create (createuserwizard1.username, true );
P. QQ = (textbox) createuserwizard1.createuserstep. contenttemplatecontainer. findcontrol ("QQ"). Text. Trim ();
P. Address = (textbox) createuserwizard1.createuserstep. contenttemplatecontainer. findcontrol ("Address"). Text. Trim ();
P. Phone = (textbox) createuserwizard1.createuserstep. contenttemplatecontainer. findcontrol ("phone"). Text. Trim (); p. Save (); // Save the modification
}
2. Write the UI by yourself. This method is recommended for personal use. It is flexible and can use 2005 powerful verification controls.
The page section is relatively simple and skipped. The Code section is described in detail below.
In this case, we need to use the createuser () method of membership. We will not introduce the syntax. It will return a membershipcreatestatus enumeration class based on the result of creating a user. It contains detailed error information about all Failed User Creation. You only need to return the corresponding prompt to the interface based on its value, such as the user name already exists and the email already exists.
We can still use the profile or custom membershipinfo table method for user information.
List the methods used to create a user for a profile. SQL statements are relatively simple and skipped.
Protected void button#click (Object sender, eventargs E)
{
Membershipcreatestatus status;
Membershipuser newuser = membership. createuser (username. text. trim (), password. text. trim (), email. text. trim (), question. text. trim (), answer. text. trim (), true, out status );
// Use membership to create a user and return the result to membershipcreatestatus
If (newuser = NULL) // if no new user exists, an error occurs.
{
Geterrormessage (Status );
// Call the geterrormessage function to return detailed error information
} Else {
Roles. addusertorole (newuser. username, "Jiancai ");
// Add the user to the corresponding group profilecommon
P = (profilecommon) profilecommon. Create (newuser. username, true );
P. QQ = QQ. Text. Trim ();
P. Address = address. Text. Trim ();
P. Phone = phone. Text. Trim ();
P. Save ();
}
}
Public void geterrormessage (membershipcreatestatus status)
{
Switch (Status)
{
Case membershipcreatestatus. duplicateusername: displayalert ("the current user already exists. Please reselect ");
Break;
// For other error messages, see the membershipcreatestatus enumeration class of msdn.
Default: displayalert ("failed to register 00000000 users. Please check your username, password, and other information ");
Break;
}
}
Personal Opinion: it is convenient to adopt the profile method. Because the profile is of a strong type, you can use the smart sensing function to reduce the input of code. When using a custom data table method, you need to input a large number of SQL statements, but the query speed is relatively fast and the performance is relatively strong, due to roles. the getusersinrole () method cannot read data by PAGE, and only all data can be read at a time. Self-writing SQL statements can be easily combined with root pages. The profile method is not recommended as the number of users increases.
1. Extend the createuserwizard control. You can use its template column. Note the following: User Name, password, question, answer, email, their IDs must be username, password, question, answer, and email. Otherwise, an error occurs and the verification control cannot be used at this time. Suspected to be a bug in IDE.
As shown below, the defined style should be:
<Wizardsteps>
<Asp: createuserwizardstep runat = "server"> Custom Code <contenttemplate>
</Contenttemplate>
</ASP: createuserwizardstep>
</Wizardsteps>
Code Section:
Protected void createuserwizardinclucreateduser (Object sender, eventargs E)
{
// Because the system will automatically create basic information tables for you, you only need to modify the profile or membershipinfo mark.
Roles. addusertorole (createuserwizard1.username, "Shop ");
// Add a user to the corresponding group
Profilecommon P = (profilecommon) profilecommon. Create (createuserwizard1.username, true );
P. QQ = (textbox) createuserwizard1.createuserstep. contenttemplatecontainer. findcontrol ("QQ"). Text. Trim ();
P. Address = (textbox) createuserwizard1.createuserstep. contenttemplatecontainer. findcontrol ("Address"). Text. Trim ();
P. Phone = (textbox) createuserwizard1.createuserstep. contenttemplatecontainer. findcontrol ("phone"). Text. Trim (); p. Save (); // Save the modification
}
2. Write the UI by yourself. This method is recommended for personal use. It is flexible and can use 2005 powerful verification controls.
The page section is relatively simple and skipped. The Code section is described in detail below.
In this case, we need to use the createuser () method of membership. We will not introduce the syntax. It will return a membershipcreatestatus enumeration class based on the result of creating a user. It contains detailed error information about all Failed User Creation. You only need to return the corresponding prompt to the interface based on its value, such as the user name already exists and the email already exists.
We can still use the profile or custom membershipinfo table method for user information.
List the methods used to create a user for a profile. SQL statements are relatively simple and skipped.
Protected void button#click (Object sender, eventargs E)
{
Membershipcreatestatus status;
Membershipuser newuser = membership. createuser (username. text. trim (), password. text. trim (), email. text. trim (), question. text. trim (), answer. text. trim (), true, out status );
// Use membership to create a user and return the result to membershipcreatestatus
If (newuser = NULL) // if no new user exists, an error occurs.
{
Geterrormessage (Status );
// Call the geterrormessage function to return detailed error information
} Else {
Roles. addusertorole (newuser. username, "Jiancai ");
// Add the user to the corresponding group profilecommon
P = (profilecommon) profilecommon. Create (newuser. username, true );
P. QQ = QQ. Text. Trim ();
P. Address = address. Text. Trim ();
P. Phone = phone. Text. Trim ();
P. Save ();
}
}
Public void geterrormessage (membershipcreatestatus status)
{
Switch (Status)
{
Case membershipcreatestatus. duplicateusername: displayalert ("the current user already exists. Please reselect ");
Break;
// For other error messages, see the membershipcreatestatus enumeration class of msdn.
Default: displayalert ("failed to register 00000000 users. Please check your username, password, and other information ");
Break;
}
}
Personal Opinion: it is convenient to adopt the profile method. Because the profile is of a strong type, you can use the smart sensing function to reduce the input of code. When using a custom data table method, you need to input a large number of SQL statements, but the query speed is relatively fast and the performance is relatively strong, due to roles. the getusersinrole () method cannot read data by PAGE, and only all data can be read at a time. Self-writing SQL statements can be easily combined with root pages. The profile method is not recommended as the number of users increases.
1. Extend the createuserwizard control. You can use its template column. Note the following: User Name, password, question, answer, email, their IDs must be username, password, question, answer, and email. Otherwise, an error occurs and the verification control cannot be used at this time. Suspected to be a bug in IDE.
As shown below, the defined style should be:
<Wizardsteps>
<Asp: createuserwizardstep runat = "server"> Custom Code <contenttemplate>
</Contenttemplate>
</ASP: createuserwizardstep>
</Wizardsteps>
Code Section:
Protected void createuserwizardinclucreateduser (Object sender, eventargs E)
{
// Because the system will automatically create basic information tables for you, you only need to modify the profile or membershipinfo mark.
Roles. addusertorole (createuserwizard1.username, "Shop ");
// Add a user to the corresponding group
Profilecommon P = (profilecommon) profilecommon. Create (createuserwizard1.username, true );
P. QQ = (textbox) createuserwizard1.createuserstep. contenttemplatecontainer. findcontrol ("QQ"). Text. Trim ();
P. Address = (textbox) createuserwizard1.createuserstep. contenttemplatecontainer. findcontrol ("Address"). Text. Trim ();
P. Phone = (textbox) createuserwizard1.createuserstep. contenttemplatecontainer. findcontrol ("phone"). Text. Trim (); p. Save (); // Save the modification
}
2. Write the UI by yourself. This method is recommended for personal use. It is flexible and can use 2005 powerful verification controls.
The page section is relatively simple and skipped. The Code section is described in detail below.
In this case, we need to use the createuser () method of membership. We will not introduce the syntax. It will return a membershipcreatestatus enumeration class based on the result of creating a user. It contains detailed error information about all Failed User Creation. You only need to return the corresponding prompt to the interface based on its value, such as the user name already exists and the email already exists.
We can still use the profile or custom membershipinfo table method for user information.
List the methods used to create a user for a profile. SQL statements are relatively simple and skipped.
Protected void button#click (Object sender, eventargs E)
{
Membershipcreatestatus status;
Membershipuser newuser = membership. createuser (username. text. trim (), password. text. trim (), email. text. trim (), question. text. trim (), answer. text. trim (), true, out status );
// Use membership to create a user and return the result to membershipcreatestatus
If (newuser = NULL) // if no new user exists, an error occurs.
{
Geterrormessage (Status );
// Call the geterrormessage function to return detailed error information
} Else {
Roles. addusertorole (newuser. username, "Jiancai ");
// Add the user to the corresponding group profilecommon
P = (profilecommon) profilecommon. Create (newuser. username, true );
P. QQ = QQ. Text. Trim ();
P. Address = address. Text. Trim ();
P. Phone = phone. Text. Trim ();
P. Save ();
}
}
Public void geterrormessage (membershipcreatestatus status)
{
Switch (Status)
{
Case membershipcreatestatus. duplicateusername: displayalert ("the current user already exists. Please reselect ");
Break;
// For other error messages, see the membershipcreatestatus enumeration class of msdn.
Default: displayalert ("failed to register 00000000 users. Please check your username, password, and other information ");
Break;
}
}
Personal Opinion: it is convenient to adopt the profile method. Because the profile is of a strong type, you can use the smart sensing function to reduce the input of code. When using a custom data table method, you need to input a large number of SQL statements, but the query speed is relatively fast and the performance is relatively strong, due to roles. the getusersinrole () method cannot read data by PAGE, and only all data can be read at a time. Self-writing SQL statements can be easily combined with root pages. The profile method is not recommended as the number of users increases.
Iii. Password problems.
I personally think the password is a headache. In actual development, we always need the Admin group to have the permission to modify the user's password. The password change method provided by membership can be modified only when the password prompt is answered. However, it is impossible for the Admin group to know the answer to the user's password. This is a bit funny. Is it a cultural difference between China and the West?
List my personal experiences on the study of membership passwords.
We all know that machine. config and web. config are preferred if they conflict with each other.
By default, membership uses the sha1 Method for encryption, and then adopts a mechanism to re-encrypt with passwordsalt to form the password displayed in the database. It can be seen that with the MD5 encryption cracking, Microsoft is also painstaking in terms of password security.
Some friends do not like the default sha1 encryption mode. We only need to set the following code in Web. config to overwrite the password settings in machine. config:
<Machinekey
Validationkey = "autogenerate, isolateapps"
Decryptionkey = "autogenerate, isolateapps"
Decryption = "Auto"
Validation = "MD5/sha1/clear"/>
Where:
The clear-password is stored in plaintext. The user password can be directly compared with this value without further conversion.
MD5-use the message digest 5 (MD5) hash digest to store the password. To verify credenmd5, the MD5 algorithm is used to hash the user password and compare the calculated value with the stored value. When this value is used, the plaintext password is never stored or compared. This algorithm performs better than sha1.
Sha1-use the sha1 hash digest to store the password. To verify creden, The sha1 algorithm is used to hash the user password and compare the calculated value with the stored value. The plaintext password is never stored. This algorithm provides higher security than the MD5 algorithm.
However, although membershipuser provides the GetPassword method, the password is obtained only when the password is set to clear in the encrypted form, that is, the password exists in the database in the clear form. In changepassword, you must provide the old password or prompt the answer to the password before you can modify it. It causes great inconvenience to user management. I have found a lot of information. By the way, Microsoft's membership mechanism originated from csblog and has been modified.
Csblog password policy: First encrypt the password entered by the user (sha1 or MD5), and then perform DES encryption on the encrypted password Based on the automatically generated key. However, when I encrypt the data using the csblog method, the format is the same, but the password is different. I am currently playing it. You are also welcome to discuss it together.
If passwordsalt and password are fixed, the user password must be. So currently, one of the methods I have taken is to reset the user's password function.
First, obtain passwordsalt and password for the known user password, and then replace the passwordsalt and password fields of the corresponding user. At this time, the user's password has been restored to a known password.
It is undeniable that membership has created great convenience for our development. Its convenient roles function provides a good solution for permission management. 2005 many functions have evolved from csblog, an excellent open-source project. If you are interested, you can study csblog to learn more about the operating mechanism of membership. Due to the limited length, I will not repeat the descriptions mentioned in msdn. I will only introduce the skills not listed on msdn and some of my experiences in project development. ASP. NET 2.0 provides important security advantages for websites that use form authentication. By providing the User Configuration File Repository and role support, form authentication will be out of ASP. NET's internal view, and can be more widely implemented.
Address: http://www.cnblogs.com/hbreset/