ASP.NET Core 的 identity 是一种需要用户登录的会员系统,用户可以创建一个登录信息存储在 Identity 的的账号,
或者也可以使用第三方登录,支持的第三方登录包括:Facebook, Google, Microsoft Account, and Twitter.
Identity 使用Sql Server 存储用户的姓名,密码等数据,当然你也可以选择其他的存储工具进行存储
这篇教程,将会讲解如何使用Identity进行用户的注册,登录,登出
1.创建一个带认证(authentication)的web应用
- 文件->新建->项目
- 选择ASP.NET Core Web 应用程序,命名WebApp1 ,点击确定
- 然后选择web 应用程序,然后更改身份验证
- 选择个人用户账号,确定
生成的项目会提供 ASP.NET Core Identity 功能,并且 Identity area 会暴露 下面几个 终端(endpoint):
- /Identity/Account/Login
- /Identity/Account/Logout
- /Identity/Account/Manage
2.迁移
观察生成的代码,发现migration已经生成了,只需要更新到数据库
在nuget 程序控制台中,输入:
代码语言:javascript复制Update-Database
直接在vs中的视图,打开sql server 对象管理器,查看数据库效果,确认数据库更新成功:
3.配置 Identity 服务(Identity service)
服务被添加到了StartUp下的 ConfigureServices方法中
代码语言:javascript复制public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
//这里对Identity做一些配置
services.Configure<IdentityOptions>(options =>
{
// Password settings.密码配置
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.锁定设置
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings.用户设置
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@ ";
options.User.RequireUniqueEmail = false;
});
services.ConfigureApplicationCookie(options =>
{
// Cookie settings 缓存设置
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
options.LoginPath = "/Identity/Account/Login";
options.AccessDeniedPath = "/Identity/Account/AccessDenied";
options.SlidingExpiration = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
4.添加 注册,登录,登录功能
- 在解决方案的项目上,右键添加->新搭建基架的项目
- 选择标识,添加
- 然后选择你想添加的项
这里的数据上下文中需要选中一个数据的,注意
之后,会生成相应的一些文件,包括注册,登录,登出
5.现在再看下,生成的代码
注册
代码语言:javascript复制public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password); //创建账户
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); //生成邮箱验证码
var callbackUrl = Url.Page( //生成验证的回调地址
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", //发送邮箱验证邮件
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
await _signInManager.SignInAsync(user, isPersistent: false); //登录
return LocalRedirect(returnUrl);
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
创建成功后,会直接显示登录状态
登录
代码语言:javascript复制public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout,
// set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email, //密码登录
Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded) //登录成功
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor) //两步验证
{
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
}
if (result.IsLockedOut) //锁定
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
登出
代码语言:javascript复制public async Task<IActionResult> OnPost(string returnUrl = null)
{
await _signInManager.SignOutAsync(); //登出
_logger.LogInformation("User logged out.");
if (returnUrl != null)
{
return LocalRedirect(returnUrl);
}
else
{
return Page();
}
}
登录页面
代码语言:javascript复制@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity"
asp-page="/Account/Manage/Index"
title="Manage">Hello@User.Identity.Name!</a>
</li>
<li class="nav-item">
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout"
asp-route-returnUrl="@Url.Page("/", new { area = "" })"
method="post">
<button type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
}
</ul>
6.验证Identity
默认的web项目模板允许匿名访问到主页的,为了验证Identity,给Privacy 页面增加 [Authorize]
代码语言:javascript复制using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace WebApp1.Pages
{
[Authorize]
public class PrivacyModel : PageModel
{
public void OnGet()
{
}
}
}
7.运行
测试注册,登录,登出功能
以及认证效果对比(即Privacy页面增加Authrize前后):
加之前:不需要登录,即可访问Privacy页面
加之后:需要登录,才能访问此页面
这里先记录添加Identity操作流程,之后会具体讲解一些功能点