首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET MVC Membership 註冊常見錯誤:IsValid 永遠為 false 與 Web.config 陷阱

     編輯:關於ASP.NET

使用 ASP.NET Membership 實作註冊功能時,Membership.CreateUser 返回 MembershipCreateStatus.InvalidPassword 或 InvalidEmail,導致 ModelState.IsValid 通過但建立失敗。根因多在 web.config Membership 設定與模型驗證屬性不一致。

現象代碼

[HttpPost]
public ActionResult Register(RegisterModel model) {
    if (ModelState.IsValid) {
        MembershipCreateStatus status;
        Membership.CreateUser(model.UserName, model.Password, model.Email, 
            passwordQuestion: null, passwordAnswer: null, 
            isApproved: true, providerUserKey: null, out status);
        if (status == MembershipCreateStatus.Success) {
            FormsAuthentication.SetAuthCookie(model.UserName, false);
            return RedirectToAction("LogOn", "Account");
        }
        ModelState.AddModelError("", ErrorCodeToString(status));
    }
    return View(model);
}

核心陷阱:web.config 設定 vs DataAnnotations

設定項web.config MembershipRegisterModel Attribute衝突後果
密碼長度minRequiredPasswordLength="7"[StringLength(100, MinimumLength=6)]前端驗證通過 6 字,Membership 拒絕 → InvalidPassword
非字母數字字符數minRequiredNonalphanumericCharacters="1"無對應驗證用戶輸入純字母數字 → InvalidPassword
密碼強度正則passwordStrengthRegularExpression=""[RegularExpression(...)]雙重驗證邏輯不一致
郵件唯一requiresUniqueEmail="true"[Remote("CheckEmail", "Account")]並發註冊同郵件 → DuplicateEmail
用戶名格式無內建限制[RegularExpression(@"^\w+$")]Membership 允許郵件作用戶名,模型拒絕

標準 web.config 範例 (與預設模板一致)

<membership defaultProvider="AspNetSqlMembershipProvider">
  <providers>
    <clear/>
    <add name="AspNetSqlMembershipProvider"
         type="System.Web.Security.SqlMembershipProvider"
         connectionStringName="ApplicationServices"
         enablePasswordRetrieval="false"
         enablePasswordReset="true"
         requiresQuestionAndAnswer="false"
         requiresUniqueEmail="true"
         maxInvalidPasswordAttempts="5"
         minRequiredPasswordLength="6"
         minRequiredNonalphanumericCharacters="0"
         passwordAttemptWindow="10"
         applicationName="/" />
  </providers>
</membership>

RegisterModel 正確驗證屬性 (對應上述 config)

public class RegisterModel {
    [Required]
    [Display(Name = "用戶名")]
    [StringLength(50, MinimumLength = 3)]
    [RegularExpression(@"^[\w\u4e00-\u9fa5]+$", ErrorMessage = "僅限字母、數字、下劃線、中文")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "密碼")]
    [StringLength(100, MinimumLength = 6)] // 對應 minRequiredPasswordLength=6
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "確認密碼")]
    [Compare("Password", ErrorMessage = "兩次輸入不一致")]
    public string ConfirmPassword { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "電子郵件")]
    [Remote("CheckEmailExists", "Account", ErrorMessage = "郵件已被註冊")]
    public string Email { get; set; }
}

錯誤碼轉換輔助方法

private string ErrorCodeToString(MembershipCreateStatus status) {
    return status switch {
        MembershipCreateStatus.DuplicateUserName => "用戶名已存在",
        MembershipCreateStatus.DuplicateEmail => "郵件已被註冊",
        MembershipCreateStatus.InvalidPassword => "密碼不符合要求 (長度、特殊字符)",
        MembershipCreateStatus.InvalidEmail => "郵件格式無效",
        MembershipCreateStatus.InvalidUserName => "用戶名包含非法字符",
        MembershipCreateStatus.ProviderError => "提供者錯誤,請稍後再試",
        _ => "未知錯誤"
    };
}

避坑檢查清單

  • ✅ web.config Membership 設定與 Model 驗證屬性完全一致 (長度、特殊字符、唯一性)。
  • ✅ 密碼策略在前端 (JavaScript) 同步提示,減少往返。
  • ✅ CreateUser 失敗時保留 ModelState,將 Membership 錯誤碼轉為友善訊息加入 ModelState.AddModelError。
  • ✅ 郵件唯一性驗證:Remote 屬性 + 伺服端 Membership.GetUserNameByEmail 檢查,但仍需捕獲 DuplicateEmail 兜底 (並發)。
  • ✅ 考慮遷移至 ASP.NET Identity (OWIN/Katana/Core),提供更靈活的密碼策略、外部登入、Claims、兩因子認證。

Identity 遷移提示

// Startup.cs
services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

// 密碼策略配置
services.Configure<IdentityOptions>(options => {
    options.Password.RequireDigit = false;
    options.Password.RequiredLength = 6;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireUppercase = false;
    options.Password.RequireLowercase = false;
    options.User.RequireUniqueEmail = true;
});
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved