如何更改身份验证属性
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">
© 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:
我使用.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">
© 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: