怎么在MVC中使用自定义Membership
首先我们来看看微软自带的membership:
我们打开系统下aspnet_regsql.exe 地址一般位于:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 如果没问题一般都是在这个目录下面如果framework里面有多个版本可以选择V2.0以上版本即可
我装的window7打开的是framework v4.0 图片如下:
我们点击下一步:
默认下一步:
这一步我们选择登录方式然后选择数据库下一步
我选中了agebook 数据 然后我用sql server服务管理器打开看看是不是自动给我们生成了一些表。自带的还是不少表 但是我们为了要使用自己的会员表所以只是给大家看看了 我个人认为自带的不好用。
我们要自定义Membership类所以还是自己定义一个用户表吧
这个表待会儿我们会用到:
首先我们用VS2012创建一个MVC应用程序
我们先看看MembershipProvider这个系统自带的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | using System; using System.Configuration.Provider; using System.Runtime; using System.Runtime.CompilerServices; using System.Web.Configuration; namespace System.Web.Security { // 摘要: // 定义 ASP.NET 为使用自定义成员资格提供程序提供成员资格服务而实现的协定。 [TypeForwardedFrom( "System.Web, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a" )] public abstract class MembershipProvider : ProviderBase { // 摘要: // 初始化 System.Web.Security.MembershipProvider 类的新实例。 [TargetedPatchingOptOut( "Performance critical to inline this type of method across NGen image boundaries" )] protected MembershipProvider(); // 摘要: // 使用自定义成员资格提供程序的应用程序的名称。 // // 返回结果: // 使用自定义成员资格提供程序的应用程序的名称。 public abstract string ApplicationName { get ; set ; } // // 摘要: // 指示成员资格提供程序是否配置为允许用户重置其密码。 // // 返回结果: // 如果成员资格提供程序支持密码重置,则为 true;否则为 false。默认值为 true。 public abstract bool EnablePasswordReset { get ; } // // 摘要: // 指示成员资格提供程序是否配置为允许用户检索其密码。 // // 返回结果: // 如果成员资格提供程序配置为支持密码检索,则为 true,否则为 false。默认值为 false。 public abstract bool EnablePasswordRetrieval { get ; } // // 摘要: // 获取锁定成员资格用户前允许的无效密码或无效密码提示问题答案尝试次数。 // // 返回结果: // 锁定成员资格用户之前允许的无效密码或无效密码提示问题答案尝试次数。 public abstract int MaxInvalidPasswordAttempts { get ; } // // 摘要: // 获取有效密码中必须包含的最少特殊字符数。 // // 返回结果: // 有效密码中必须包含的最少特殊字符数。 public abstract int MinRequiredNonAlphanumericCharacters { get ; } // // 摘要: // 获取密码所要求的最小长度。 // // 返回结果: // 密码所要求的最小长度。 public abstract int MinRequiredPasswordLength { get ; } // // 摘要: // 获取在锁定成员资格用户之前允许的最大无效密码或无效密码提示问题答案尝试次数的分钟数。 // // 返回结果: // 在锁定成员资格用户之前允许的最大无效密码或无效密码提示问题答案尝试次数的分钟数。 public abstract int PasswordAttemptWindow { get ; } // // 摘要: // 获取一个值,该值指示在成员资格数据存储区中存储密码的格式。 // // 返回结果: // System.Web.Security.MembershipPasswordFormat 值之一,该值指示在数据存储区中存储密码的格式。 public abstract MembershipPasswordFormat PasswordFormat { get ; } // // 摘要: // 获取用于计算密码的正则表达式。 // // 返回结果: // 用于计算密码的正则表达式。 public abstract string PasswordStrengthRegularExpression { get ; } // // 摘要: // 获取一个值,该值指示成员资格提供程序是否配置为要求用户在进行密码重置和检索时回答密码提示问题。 // // 返回结果: // 如果密码重置和检索需要提供密码提示问题答案,则为 true;否则为 false。默认值为 true。 public abstract bool RequiresQuestionAndAnswer { get ; } // // 摘要: // 获取一个值,指示成员资格提供程序是否配置为要求每个用户名具有唯一的电子邮件地址。 // // 返回结果: // 如果成员资格提供程序要求唯一的电子邮件地址,则返回 true;否则返回 false。默认值为 true。 public abstract bool RequiresUniqueEmail { get ; } // 摘要: // 在创建用户、更改密码或重置密码时发生。 public event MembershipValidatePasswordEventHandler ValidatingPassword; // 摘要: // 处理更新成员资格用户密码的请求。 // // 参数: // username: // 为其更新密码的用户。 // // oldPassword: // 指定的用户的当前密码。 // // newPassword: // 指定的用户的新密码。 // // 返回结果: // 如果密码更新成功,则为 true;否则为 false。 public abstract bool ChangePassword( string username, string oldPassword, string newPassword); // // 摘要: // 处理更新成员资格用户的密码提示问题和答案的请求。 // // 参数: // username: // 要为其更改密码提示问题和答案的用户。 // // password: // 指定的用户的密码。 // // newPasswordQuestion: // 指定的用户的新密码提示问题。 // // newPasswordAnswer: // 指定的用户的新密码提示问题答案。 // // 返回结果: // 如果成功更新密码提示问题和答案,则为 true;否则,为 false。 public abstract bool ChangePasswordQuestionAndAnswer( string username, string password, string newPasswordQuestion, string newPasswordAnswer); // // 摘要: // 将新的成员资格用户添加到数据源。 // // 参数: // username: // 新用户的用户名。 // // password: // 新用户的密码。 // // email: // 新用户的电子邮件地址。 // // passwordQuestion: // 新用户的密码提示问题。 // // passwordAnswer: // 新用户的密码提示问题答案。 // // isApproved: // 是否允许验证新用户。 // // providerUserKey: // 成员资格数据源中该用户的唯一标识符。 // // status: // 一个 System.Web.Security.MembershipCreateStatus 枚举值,指示是否已成功创建用户。 // // 返回结果: // 一个用新创建的用户的信息填充的 System.Web.Security.MembershipUser 对象。 public abstract MembershipUser CreateUser( string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status); // // 摘要: // 解密已加密的密码。 // // 参数: // encodedPassword: // 一个字节数组,包含要解密的加密密码。 // // 返回结果: // 包含已解密密码的字节数组。 // // 异常: // System.Configuration.Provider.ProviderException: // 将 System.Web.Configuration.MachineKeySection.ValidationKey 属性或 System.Web.Configuration.MachineKeySection.DecryptionKey // 属性设置为 AutoGenerate。 protected virtual byte [] DecryptPassword( byte [] encodedPassword); // // 摘要: // 从成员资格数据源删除一个用户。 // // 参数: // username: // 要删除的用户的名称。 // // deleteAllRelatedData: // 如果为 true,则从数据库中删除与该用户相关的数据;如果为 false,则将与该用户相关的数据保留在数据库。 // // 返回结果: // 如果用户被成功删除,则为 true;否则为 false。 public abstract bool DeleteUser( string username, bool deleteAllRelatedData); // // 摘要: // 对密码进行加密。 // // 参数: // password: // 包含要加密的密码的字节数组。 // // 返回结果: // 包含已加密的密码的字节数组。 // // 异常: // System.Configuration.Provider.ProviderException: // 将 System.Web.Configuration.MachineKeySection.ValidationKey 属性或 System.Web.Configuration.MachineKeySection.DecryptionKey // 属性设置为 AutoGenerate。 [TargetedPatchingOptOut( "Performance critical to inline this type of method across NGen image boundaries" )] protected virtual byte [] EncryptPassword( byte [] password); // // 摘要: // 使用指定的密码兼容性模式对指定密码进行加密。 // // 参数: // password: // 包含要加密的密码的字节数组。 // // legacyPasswordCompatibilityMode: // 成员资格密码兼容性模式。 // // 返回结果: // 包含已加密的密码的字节数组。 protected virtual byte [] EncryptPassword( byte [] password, MembershipPasswordCompatibilityMode legacyPasswordCompatibilityMode); // // 摘要: // 获取一个成员资格用户的集合,其中的电子邮件地址包含要匹配的指定电子邮件地址。 // // 参数: // emailToMatch: // 要搜索的电子邮件地址。 // // pageIndex: // 要返回的结果页的索引。pageIndex 从零开始。 // // pageSize: // 要返回的结果页的大小。 // // totalRecords: // 匹配用户的总数。 // // 返回结果: // 包含一页 pageSizeSystem.Web.Security.MembershipUser 对象的 System.Web.Security.MembershipUserCollection // 集合,这些对象从 pageIndex 指定的页开始。 public abstract MembershipUserCollection FindUsersByEmail( string emailToMatch, int pageIndex, int pageSize, out int totalRecords); // // 摘要: // 获取一个成员资格用户的集合,其中的用户名包含要匹配的指定用户名。 // // 参数: // usernameToMatch: // 要搜索的用户名。 // // pageIndex: // 要返回的结果页的索引。pageIndex 从零开始。 // // pageSize: // 要返回的结果页的大小。 // // totalRecords: // 匹配用户的总数。 // // 返回结果: // 包含一页 pageSizeSystem.Web.Security.MembershipUser 对象的 System.Web.Security.MembershipUserCollection // 集合,这些对象从 pageIndex 指定的页开始。 public abstract MembershipUserCollection FindUsersByName( string usernameToMatch, int pageIndex, int pageSize, out int totalRecords); // // 摘要: // 获取数据源中的所有用户的集合,并显示在数据页中。 // // 参数: // pageIndex: // 要返回的结果页的索引。pageIndex 从零开始。 // // pageSize: // 要返回的结果页的大小。 // // totalRecords: // 匹配用户的总数。 // // 返回结果: // 包含一页 pageSizeSystem.Web.Security.MembershipUser 对象的 System.Web.Security.MembershipUserCollection // 集合,这些对象从 pageIndex 指定的页开始。 public abstract MembershipUserCollection GetAllUsers( int pageIndex, int pageSize, out int totalRecords); // // 摘要: // 获取当前访问该应用程序的用户数。 // // 返回结果: // 当前访问该应用程序的用户数。 public abstract int GetNumberOfUsersOnline(); // // 摘要: // 从数据源获取指定用户名所对应的密码。 // // 参数: // username: // 为其检索密码的用户。 // // answer: // 用户的密码提示问题答案。 // // 返回结果: // 指定用户名所对应的密码。 public abstract string GetPassword( string username, string answer); // // 摘要: // 根据成员资格用户的唯一标识符从数据源获取用户信息。提供一个更新用户最近一次活动的日期/时间戳的选项。 // // 参数: // providerUserKey: // 要获取其信息的成员资格用户的唯一标识符。 // // userIsOnline: // 如果为 true,则更新用户最近一次活动的日期/时间戳;如果为 false,则返回用户信息,但不更新用户最近一次活动的日期/时间戳。 // // 返回结果: // 用数据源中指定用户的信息填充的 System.Web.Security.MembershipUser 对象。 public abstract MembershipUser GetUser( object providerUserKey, bool userIsOnline); // // 摘要: // 从数据源获取用户的信息。提供一个更新用户最近一次活动的日期/时间戳的选项。 // // 参数: // username: // 要获取其信息的用户名。 // // userIsOnline: // 如果为 true,则更新用户最近一次活动的日期/时间戳;如果为 false,则返回用户信息,但不更新用户最近一次活动的日期/时间戳。 // // 返回结果: // 用数据源中指定用户的信息填充的 System.Web.Security.MembershipUser 对象。 public abstract MembershipUser GetUser( string username, bool userIsOnline); // // 摘要: // 获取与指定的电子邮件地址关联的用户名。 // // 参数: // email: // 要搜索的电子邮件地址。 // // 返回结果: // 与指定的电子邮件地址关联的用户名。如果未找到匹配项,则返回 null。 public abstract string GetUserNameByEmail( string email); // // 摘要: // 如果定义了事件处理程序,则引发 System.Web.Security.MembershipProvider.ValidatingPassword // 事件。 // // 参数: // e: // 传递给 System.Web.Security.MembershipProvider.ValidatingPassword 事件处理程序的 System.Web.Security.ValidatePasswordEventArgs。 protected virtual void OnValidatingPassword(ValidatePasswordEventArgs e); // // 摘要: // 将用户密码重置为一个自动生成的新密码。 // // 参数: // username: // 为其重置密码的用户。 // // answer: // 指定的用户的密码提示问题答案。 // // 返回结果: // 指定的用户的新密码。 public abstract string ResetPassword( string username, string answer); // // 摘要: // 清除锁定,以便可以验证该成员资格用户。 // // 参数: // userName: // 要清除其锁定状态的成员资格用户。 // // 返回结果: // 如果成功取消成员资格用户的锁定,则为 true;否则为 false。 public abstract bool UnlockUser( string userName); // // 摘要: // 更新数据源中有关用户的信息。 // // 参数: // user: // 一个 System.Web.Security.MembershipUser 对象,表示要更新的用户及其更新信息。 public abstract void UpdateUser(MembershipUser user); // // 摘要: // 验证数据源中是否存在指定的用户名和密码。 // // 参数: // username: // 要验证的用户的名称。 // // password: // 指定的用户的密码。 // // 返回结果: // 如果指定的用户名和密码有效,则为 true;否则为 false。 public abstract bool ValidateUser( string username, string password); } } |
有这么多 方法 我们的写它因为要自定义一个自己的Membership类如下:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.OleDb;
using System.Data.SqlClient;
/// <summary>
/// MyMemberShip 的摘要说明
/// </summary>
public class MyMemberShip : MembershipProvider
{
public MyMemberShip()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
string connectionstring = ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString.ToString();
private bool _requiresQuestionAndAnswer;
private int _minRequiredPasswordLength;
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
if (config["requiresQuestionAndAnswer"].ToLower() == "true")
{
_requiresQuestionAndAnswer = true;
}
else
{
_requiresQuestionAndAnswer = false;
}
int.TryParse(config["minRequiredPasswordLength"], out _minRequiredPasswordLength);
//connStr = config["connectionString"];
base.Initialize(name, config);
}
public override string ApplicationName
{
get
{
throw new Exception("The method or operation is not implemented.");
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
throw new Exception("The method or operation is not implemented.");
}
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
{
throw new Exception("The method or operation is not implemented.");
}
public override MembershipUser CreateUser(string username,string password,string email,string passwordQuestion,string passwordAnswer,bool isApproved,Object providerUserKey,out MembershipCreateStatus status)
{
using (SqlConnection conn = new SqlConnection(connectionstring))
{
SqlCommand comm = new SqlCommand();
comm.CommandText = "insert into users(u_name,u_pwd,u_role) values(@cname,@cpwd,@crole)";
comm.Parameters.AddWithValue("@cname", username);
comm.Parameters.AddWithValue("@cpwd", password);
comm.Parameters.AddWithValue("@crole", "guest");
comm.Connection = conn;
conn.Open();
comm.ExecuteNonQuery();
MembershipUser user = new MembershipUser("MyMemberShip", username, providerUserKey, email, passwordQuestion, "", isApproved, true, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
status = MembershipCreateStatus.Success;
return user;
}
}
public override bool DeleteUser(string username, bool deleteAllRelatedData)
{
throw new Exception("The method or operation is not implemented.");
}
public override bool EnablePasswordReset
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override bool EnablePasswordRetrieval
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new Exception("The method or operation is not implemented.");
}
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new Exception("The method or operation is not implemented.");
}
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{
throw new Exception("The method or operation is not implemented.");
}
public override int GetNumberOfUsersOnline()
{
throw new Exception("The method or operation is not implemented.");
}
public override string GetPassword(string username, string answer)
{
throw new Exception("The method or operation is not implemented.");
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
throw new Exception("The method or operation is not implemented.");
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
throw new Exception("The method or operation is not implemented.");
}
public override string GetUserNameByEmail(string email)
{
throw new Exception("The method or operation is not implemented.");
}
public override int MaxInvalidPasswordAttempts
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override int MinRequiredNonAlphanumericCharacters
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override int MinRequiredPasswordLength
{
get { return _minRequiredPasswordLength; }
}
public override int PasswordAttemptWindow
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MembershipPasswordFormat PasswordFormat
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override string PasswordStrengthRegularExpression
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override bool RequiresQuestionAndAnswer
{
get { return _requiresQuestionAndAnswer; }
}
public override bool RequiresUniqueEmail
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override string ResetPassword(string username, string answer)
{
throw new Exception("The method or operation is not implemented.");
}
public override bool UnlockUser(string userName)
{
throw new Exception("The method or operation is not implemented.");
}
public override void UpdateUser(MembershipUser user)
{
throw new Exception("The method or operation is not implemented.");
}
public override bool ValidateUser(string username, string password)
{
using (SqlConnection conn = new SqlConnection(connectionstring))
{
SqlCommand comm = new SqlCommand();
comm.CommandText = "select count(0) from users where u_name=@cname and u_pwd=@cpwd";
comm.Parameters.AddWithValue("@cname", username);
comm.Parameters.AddWithValue("@cpwd", password);
comm.Connection = conn;
conn.Open();
return ((int)comm.ExecuteScalar()) > 0 ? true : false;
}
}
}
这个类里面包括了很多验证的方法具体我就不介绍了
接下来我们看看配置文件怎么配置:
<configuration>下
<connectionStrings>
<remove name="LocalSqlServer" />
<add name="LocalSqlServer" connectionString="Data Source=.;Initial Catalog=agebook;Persist Security Info=True;User ID=sa;Password=sa" providerName="System.Data.SqlClient" />
</connectionStrings>
记着加入forms验证
<compilation debug="true" targetFramework="4.0" />
<!--<authentication mode="Windows" />-->
<authentication mode="Forms"/>
<authorization>
<allow users="*" />
</authorization>
也可以这样:
<authentication mode="Forms">
<forms loginUrl="/Home/Login" name="login"/>
</authentication>
配置MemberShip节点
<system.web>内配置:
<membership defaultProvider="MyMemberShip" userIsOnlineTimeWindow="20">
<providers>
<remove name="AspNetSqlProvider" />
<add name="MyMemberShip"
type="MyMemberShip"
connectionStringName="SqlServices"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
passwordFormat="Hashed"
applicationName="/" />
</providers>
</membership>
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName=" LocalSqlServer " applicationName="/" />
</providers>
</profile>
最后我们在测试一下登录页面
<form action='/Home/Login' method="post">
用户名:@Html.TextBox("Username")
密码:@Html.Password("Password")
<input type="submit" value="登录" />
</form>
控制页面代码如下:
string name = Request.Form["Username"];
string pwd = Request.Form["Password"];
if (name == "" || name == null)
name = "t";
if (pwd == "" || pwd == null)
pwd = "s";
if (Membership.ValidateUser(name, pwd))
{
Response.Write("您的登录名称:" + User.Identity.Name + " <br>权限为:");
foreach (string s in Roles.GetRolesForUser(name))
{
Response.Write("<li>" + s + "</li>");
}
}
是不是感觉给自己写的登录方法差不多吧!自带的用户登录控件就带MemberShip包括以前微软最有名的一个事例 PetShop4.0也用了它,一般控件开发用的比较多些,现在不知道用的人还多不多,最近有人问我Membership这问题所以就总结一下,希望对大家有所帮助。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端