如何更改身份验证属性

How to change Identity validation properties

我使用.net core 3 版本创建了一个Identity 项目。我生成了一个迁移文件,并 Startup.cs 进行了一些配置。

public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>();
            services.AddControllersWithViews();
            services.AddRazorPages();
        }

但是如何修改注册时创建密码的规则呢? enter image description here

这是一个完整的自定义验证演示,您可以select需要更改的部分:

1.Create UserLoginDto.cs class 并为电子邮件、密码设置验证并创建 UserRegistrationDto.cs class 以注册并为所有属性设置验证

 public class UserRegistrationDto
    {
        [Required(ErrorMessage = "Name is required")]
        [StringLength(100)]
        public string Name { get; set; }

        [EmailAddress(ErrorMessage = "Invalid email address")]
        [Required(ErrorMessage = "Email is required")]
        public string Email { get; set; }

        [Required(ErrorMessage = "Password is required")]
        [RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$",
         ErrorMessage = "Characters are not allowed.")]

        public string Password { get; set; }

        [Required(ErrorMessage = "Confirm password is required")]
       
        [Compare("Password", ErrorMessage = "The Password and Confirm Password do not match.")]
        public string ConfirmPassword { get; set; }

        public string PhoneNumber { get; set; }
    }

 public class UserLoginDto
    {
        [Required(ErrorMessage = "Email is required")]
        [EmailAddress(ErrorMessage = "Invalid email address")]
        public string Email { get; set; }

        [Required(ErrorMessage = "Password is required")]
        [DataType(DataType.Password)]
        public string Password { get; set; }

        [Display(Name = "Remember me")]
        public bool RememberMe { get; set; }
    }

2.Inject UserManager 和 SignInManager 身份 class进入它们的构造函数。

 public class AccountController : Controller
    {
        private readonly UserManager<IdentityUser> userManager;
        private readonly SignInManager<IdentityUser> signInManager;
        public AccountController(UserManager<IdentityUser> userManager,
            SignInManager<IdentityUser> signInManager)
        {
            this.userManager = userManager;
            this.signInManager = signInManager;
        }

3.Create这样的注册登录方式

     public class AccountController : Controller
        {
            private readonly UserManager<IdentityUser> userManager;
            private readonly SignInManager<IdentityUser> signInManager;
            public AccountController(UserManager<IdentityUser> userManager,
                SignInManager<IdentityUser> signInManager)
            {
                this.userManager = userManager;
                this.signInManager = signInManager;
            }
    
    
            [HttpGet, AllowAnonymous]
            public IActionResult Register()
            {
                UserRegistrationDto model = new UserRegistrationDto();
                return View(model);
            }
    
            [HttpPost, AllowAnonymous]
            public async Task<IActionResult> Register(UserRegistrationDto request)
            {
                if (ModelState.IsValid)
                {
                    var userCheck = await userManager.FindByEmailAsync(request.Email);
                    if (userCheck == null)
                    {
                        var user = new IdentityUser
                        {
                            UserName = request.Email,
                            NormalizedUserName = request.Email,
                            Email = request.Email,
                            PhoneNumber = request.PhoneNumber,
                            EmailConfirmed = true,
                            PhoneNumberConfirmed = true,
                        };
                        var result = await userManager.CreateAsync(user, request.Password);
                        if (result.Succeeded)
                        {
                            return RedirectToAction("Login");
                        }
                        else
                        {
                            if (result.Errors.Count() > 0)
                            {
                                foreach (var error in result.Errors)
                                {
                                    ModelState.AddModelError("message", error.Description);
                                }
                            }
                            return View(request);
                        }
                    }
                    else
                    {
                        ModelState.AddModelError("message", "Email already exists.");
                        return View(request);
                    }
                }
                return View(request);
    
            }
    
            [HttpGet]
            [AllowAnonymous]
            public IActionResult Login()
            {
                UserLoginDto model = new UserLoginDto();
                return View(model);
            }
    
            [HttpPost]
            [AllowAnonymous]
            public async Task<IActionResult> Login(UserLoginDto model)
            {
                if (ModelState.IsValid)
                {
                    var user = await userManager.FindByEmailAsync(model.Email);
                    if (user != null && !user.EmailConfirmed)
                    {
                        ModelState.AddModelError("message", "Email not confirmed yet");
                        return View(model);
    
                    }
                    if (await userManager.CheckPasswordAsync(user, model.Password) == false)
                    {
                        ModelState.AddModelError("message", "Invalid credentials");
                        return View(model);
    
                    }
    
                    var result = await signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, true);
    
                    if (result.Succeeded)
                    {
                        await userManager.AddClaimAsync(user, new Claim("UserRole", "Admin"));
                        return RedirectToAction("Dashboard");
                    }
                    else if (result.IsLockedOut)
                    {
                        return View("AccountLocked");
                    }
                    else
                    {
                        ModelState.AddModelError("message", "Invalid login attempt");
                        return View(model);
                    }
                    }
                    return View(model);
                }
 [Authorize]
        public IActionResult Dashboard()
        {
            return View();
        }
        public async Task<IActionResult> Logout()
        {
            await signInManager.SignOutAsync();
            return RedirectToAction("login", "account");
        }

4.Create Register.cshtml 视图

@model UserRegistrationDto
@{
    ViewData["Title"] = "Register";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container">
    <h1>Register</h1>
    @Html.ValidationSummary()
    <form asp-action="Register" asp-controller="Account" method="post">

        <div class="registerdiv">
            <div class="form-group col-sm-12">
                <label asp-for="@Model.Name" class="col-lg-3 control-label"></label>
                <br>
                <div class="col-lg-9">
                    @Html.TextBoxFor(m => m.Name, new { placeholder = "First Name", @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.Name)
                </div>
            </div>


            <div class="form-group col-sm-12">
                <label asp-for="@Model.Email" class="col-lg-3 control-label"></label>
                <br>
                <div class="col-lg-9">
                    @Html.TextBoxFor(m => m.Email, new { placeholder = "Email", @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.Email)
                </div>
            </div>

            <div class="form-group col-sm-12">
                <label asp-for="@Model.PhoneNumber" class="col-lg-3 control-label"></label>
                <br>
                <div class="col-lg-9">
                    @Html.TextBoxFor(m => m.PhoneNumber, new { placeholder = "Phone Number", @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.PhoneNumber)
                </div>
            </div>


            <div class="form-group col-sm-12">
                <label asp-for="@Model.Password" class="col-lg-3 control-label"></label>
                <br>
                <div class="col-lg-9">
                    @Html.TextBoxFor(m => m.Password, new { placeholder = "Password", @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.Password)
                </div>
            </div>

            <div class="form-group col-sm-12">
                <label asp-for="@Model.ConfirmPassword" class="col-lg-3 control-label"></label>
                <br>
                <div class="col-lg-9">
                   
                    @Html.PasswordFor(m => m.ConfirmPassword, new { placeholder = "Confirm Password", @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.ConfirmPassword)
                </div>
            </div>

            <div class="form-group">
                <div class="col-sm-12 btn-submit">
                    <button type="submit" class="btn btn-success">Sign Up</button>

                </div>
            </div>
        </div>
    </form>
</div> 
<style>
    .validation-summary-errors,.field-validation-error {
        color: red;
    }
</style>

5.Create Login.cshmt 视图

@model UserLoginDto
@{
    ViewData["Title"] = "Login";
    Layout = "~/Views/Shared/_Layout.cshtml";
}


<div class="container">
    <h1>Login</h1>
    @Html.ValidationSummary()
    <form asp-action="Login" asp-controller="Account" method="post">

        <div class="logindiv">

            <div class="form-group col-sm-12">
                <label asp-for="@Model.Email" class="col-lg-3 control-label"></label>
                <br>
                <div class="col-lg-9">
                    @Html.TextBoxFor(m => m.Email, new { placeholder = "Email", @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.Email)
                </div>
            </div>

            <div class="form-group col-sm-12">
                <label asp-for="@Model.Password" class="col-lg-3 control-label"></label>
                <br>
                <div class="col-lg-9">
                    @Html.PasswordFor(m => m.Password, new { placeholder = "Password", @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.Password)
                </div>
            </div>

            <div class="form-group">
                <div class="col-sm-12 btn-submit">
                    <button type="submit" class="btn btn-success">Login</button>
                    <a asp-action="Register" asp-controller="account">Don't have an account?Click to Register</a>

                </div>
            </div>
        </div>
    </form>
</div>  

6.Create_LoginPartial.cshmtl的局部视图,显示登录用户名,登录网站后会出现注销按钮

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebApplication221</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">WebApplication221</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <partial name="_LoginPartial" />
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2022 - WebApplication221 - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @RenderSection("Scripts", required: false)
</body>
</html>

7.Set 来自 Startup.cs class.

中 ConfigureServices 的自定义重定向 URL 路径
 public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.ConfigureApplicationCookie(options =>
            {
                options.LoginPath = $"/account/login";
                options.LogoutPath = $"/account/logout";
                options.AccessDeniedPath = $"/account/accessDenied";
            });

            services.AddControllersWithViews();
            services.AddRazorPages();
        }

8.Result: