关键词:
这节我们主要介绍ASP.NET Core Identity认证,认证是决定用户是否能够成功登录应用程序的一个过程,用户通过提供自己的用户名和密码来证明他们自己是真实用户,当登录成功时, Identity 认证用户并且赋予访问ASP.NET Core 应用程序安全资源
1、ASP.NET Core Identity如何认证
我们创建ASP.NET Core Identity Authentication特性,允许对Identity User 进行认证,首先我们创建一个HomeController并修改Index Action 返回一个字符串到View
当我们运行应用程序时,我们可以没有任何限制的访问Index action,浏览器发送匿名请求(anonymous request) 到Home Controller 的Index 方法,这个匿名请求能访问应用程序Home Controller资源,因此我们能在浏览器上看到Hello消息
现在我们给Index Action增加认证,注意Identity Authorization和Authentication不同,Authorization在Authentication之后,用户授权是指Identity授权一个用户访问应用程序资源
提交一个Identity authentication 非常容易,我们仅仅需要在Index 方法上提交一个 [Authorize] 特性,该特性位于在Microsoft.AspNetCore.Authorization命名空间,这将限制用户访问
现在我们运行app 将显示如下图
如下两点我们注意一下:
在Index 方法上使用[Authorize]特性,用户访问Controller之前需要做认证
ASP.NET Core Identity 导航到AccountController 的Login方法,这个是Identity默认登录页面,https://localhost:7296/
Account/Login?ReturnUrl=%2Fhome%2Findex 这页面可以登录应用程序,我们稍后将构建这个页面
注意URL包含查询字符串变量叫ReturnUrl,包含%2F ,%2F是一个编码的字符,代表 / ,因此认证之后,用户将跳转到应用程序的主页面,在认证之前ReturnUrl包含一个用户访问的安全页面,一旦Identity认证成功将会跳转到ReturnUrl指定的安全页面
2、修改Identity 中默认登录的URL
ASP.NET Core Identity 默认的登录地址是/Account/Login,可以通过如下代码改变默认的登录URL:
builder.Services.ConfigureApplicationCookie(opts=> opts.LoginPath = "/Authenticate/Login");
我们在这里指定了新的登录地址/Authenticate/Login 例如: https://localhost:7296/Authenticate/Login
3、ASP.NET Core Identity 登录页面
为了实现Identity认证,我们将创建两个页面登录页面和退出,在登录页面中用户将输入用户名和密码进行认证,当用户退出时,用户点击logout按钮将退出登录
3.1、ASP.NET Core Identity 登录页面
在Models文件夹下创建Login文件,实体类中包含了三个属性,分别为Email、Password、ReturnUrl
public class Login
[Required]
[DisplayName("用户名")]
public string Email get; set; = null!;
[Required]
[DisplayName("密码")]
[DataType(DataType.Password)]
public string Password get; set; = null!;
public string? ReturnUrl get; set;
Email和Password是必填字段,用户在登录过程中必须输入这两个字段,Identity 默认登录地址是https://localhost:7296 /Account/Login,因此我们需要添加一个Account 控制器,并在该控制器中添加Login 方法
[Authorize]
public class AccountController : Controller
private UserManager<AppUser> _userManager;
private SignInManager<AppUser> _signInManager;
public AccountController(UserManager<AppUser> userManager, SignInManager<AppUser> signInManager)
_userManager = userManager;
_signInManager = signInManager;
[AllowAnonymous]
public IActionResult Login(string returnUrl)
var login = new Login();
login.ReturnUrl = returnUrl;
return View(login);
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(Login login)
if (ModelState.IsValid)
var appUser = await _userManager.FindByEmailAsync(login.Email);
if (appUser != null)
await _signInManager.SignOutAsync();
var signInResult = await _signInManager.PasswordSignInAsync(appUser, login.Password, false, false);
if (signInResult.Succeeded)
return Redirect(login.ReturnUrl ?? "/");
return View(login);
我们在Controller上应用了[Authorize]特性,从而阻止匿名请求调用,在Login方法上添加了[AllowAnonymous]特性,允许匿名请求访问这个方法,login 方法必须允许匿名访问,否则我们永远无法登录,在AccountController构造函数中添加了UserManager<AppUser>和SignInManager<AppUser>引用,UserManager<T>主要负责管理Identity的用户,SignInManager<T>主要负责Identity的认证过程
private UserManager<AppUser> _userManager;
private SignInManager<AppUser> _signInManager;
public AccountController(UserManager<AppUser> userManager, SignInManager<AppUser> signInManager)
_userManager = userManager;
_signInManager = signInManager;
下面我们添加一个Http Get版本的Login方法,在该方法上使用[AllowAnonymous] 特性,可以匿名访问该方法,否则用户不能登录,这个action方法接受一个returnUrl的参数,该参数提供查询字符串,背后的原理:模型绑定将自动绑定该URL变量
[AllowAnonymous]
public IActionResult Login(string returnUrl)
var login = new Login();
login.ReturnUrl = returnUrl;
return View(login);
下面我们添加一个Post版本的Login 方法,实际上认证用户的逻辑将在该方法中,代码如下:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(Login login)
if (ModelState.IsValid)
var appUser = await _userManager.FindByEmailAsync(login.Email);
if (appUser != null)
await _signInManager.SignOutAsync();
var signInResult = await _signInManager.PasswordSignInAsync(appUser, login.Password, false, false);
if (signInResult.Succeeded)
return Redirect(login.ReturnUrl ?? "/");
return View(login);
这个方法接受Login类型的参数,可以从用户登录表单中获取email和password的值,这个方法提供了两个特性:
[AllowAnonymous] 表示允许匿名用户访问
[ValidateAntiForgeryToken] 阻止CSRF攻击
首先我们根据UserManager 的 FindByEmailAsync()方法获取到用户信息,如果用户信息不为空,我们先退出登录,然后再调用PasswordSignInAsync 进行登录,这个方法第三个参数和第四个参数分别设置成false,第三个参数表示我们不想持久化Cookie,第四个参数表示用户登录失败时是否锁定用户,该方法返回SignInResult 登录结果对象,如果成功Succeeded返回true,否则返回false,登录成功之后,跳转到客户指定的URL
我们需要创建一个Login View的登录表单,这个视图是Identity登录页面,处理用户账户登录过程,我们在Views/Account 下创建View页面,代码如下:
@model Login
@
ViewData["Title"] = "Login";
<div class="text-danger" asp-validation-summary="All"></div>
<form class="form-horizontal" role="form" method="post">
<div class="mb-3 row">
<label asp-for="Email" class="col-sm-1 control-label"></label>
<div class="col-sm-11">
<input asp-for="Email" class="form-control" />
</div>
</div>
<div class="mb-3 row">
<label asp-for="Password" class="col-sm-1 control-label"></label>
<div class="col-sm-11">
<input asp-for="Password" class="form-control" />
</div>
</div>
<div class="mb-3 row">
<div class="col-sm-11 offset-sm-1">
<button type="submit" class="btn btn-primary">登录</button>
</div>
</div>
</form>
我们测试一下刚才创建的认证功能,注册了如下用户:
姓名-tom
邮件-tom@yahoo.com
密码-Coder77@
现在我们使用用户的邮箱和密码进行登陆,如果你没有任何用户信息,你可以通过https://localhost:7296/Admin/Create创建一个用户,运行应用程序输入用户名和密码:
我们可以使用UserManager<T>的GetUserAsyns()方法类获取当前登录的用户信息并显示在View上:
编辑HomeController控制器,并获取User信息,将用户名传递到View
[Authorize]
public async Task<IActionResult> Index()
var appUser = await _userManager.GetUserAsync(HttpContext.User);
var message = "Hello " + appUser?.UserName;
return View((object)message);
4、ASP.NET Core Identity 退出页面
Logout非常简单,我们调用SignInManager的SignOutAsync方法退出登录
public async Task<IActionResult> Logout()
await _signInManager.SignOutAsync();
return RedirectToAction("Index", "Home");
Logout方法将退出登录,并跳转到Home控制器的Index方法。User.Identity.IsAuthenticated属性返回true表示用户已经登录,否则将返回 null,当用户成功登录应用程序时显示 Logout 链接。
运行应用程序并进行登录,登录之后将跳转到Home页我们能看到 Logout按钮,点击它可以退出 ASP.NET Core Identity,看下面图片:
5、ASP.NET Core Identity Cookie
ASP.NET Core Identity使用Cookie确定一个用户是否被认证,一旦这个用户被认证Cookie就会被创建并且存储在浏览器,每次HTTP请求时都会发送Cookie到服务器,当我们在浏览器中打开应用程序的任何URL,Identity就能确定请求来自哪个用户,Cookie名字为.AspNetCore.Identity.Application,我们可以在浏览器中查看到这个Cookie
Identity Cookie超时
我们可以使用IServiceCollection 的ConfigureApplication
Cookie方法设置ASP.NET Core Identity Cookie超时时间
builder.Services.ConfigureApplicationCookie(
opts =>
opts.LoginPath = "/Account/Login";
//设置Cookie名称
opts.Cookie.Name = ".AspNetCore.Identity.Application";
//设置Cookie超时时间
opts.ExpireTimeSpan = TimeSpan.FromMinutes(20);
//设置滑动时间
opts.SlidingExpiration = true;
);
ASP.NET Core Identity Remember Me
我们创建一个Remember Me功能,帮助客户记住密码,我们只需要登录一次,Identity将创建一个持久Cookie在浏览器,我们在login.cshtml的页面添加一个type=checkbox的输入框
@model Login
@
ViewData["Title"] = "Login";
<div class="text-danger" asp-validation-summary="All"></div>
<form class="form-horizontal" role="form" method="post">
<div class="mb-3 row">
<label asp-for="Email" class="col-sm-1 control-label"></label>
<div class="col-sm-11">
<input asp-for="Email" class="form-control" />
</div>
</div>
<div class="mb-3 row">
<label asp-for="Password" class="col-sm-1 control-label"></label>
<div class="col-sm-11">
<input asp-for="Password" class="form-control" />
</div>
</div>
<div class="mb-3 row">
<label asp-for="RememberMe" class="col-sm-1 control-label"></label>
<div class="col-sm-11">
<input type="checkbox" asp-for="RememberMe" />
</div>
</div>
<div class="mb-3 row">
<div class="col-sm-11 offset-sm-1">
<button type="submit" class="btn btn-primary">登录</button>
</div>
</div>
</form>
并在Login实体类中增加属性:
public class Login
[Required]
[DisplayName("用户名")]
public string Email get; set; = null!;
[Required]
[DisplayName("密码")]
[DataType(DataType.Password)]
public string Password get; set; = null!;
public string? ReturnUrl get; set;
[Required]
[DisplayName("记住密码")]
public bool RememberMe get; set;
修改Login登录方法
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(Login login)
if (ModelState.IsValid)
var appUser = await _userManager.FindByEmailAsync(login.Email);
if (appUser != null)
await _signInManager.SignOutAsync();
var signInResult = await _signInManager.PasswordSignInAsync(appUser, login.Password,
login.RememberMe, false);
if (signInResult.Succeeded)
return Redirect(login.ReturnUrl ?? "/");
ModelState.AddModelError(nameof(login.Email),"Login Failed: Invalid Email or password");
return View(login);
总结
这节我们主要介绍了在Identity如何认证用户,我们可以为我们WebSite区域做一些安全认证
源代码地址:
https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/AspNetCore.Identity/Identity
补充:ASP.NET Core Identity 系列之三 源代码地址以废弃,上面那是最新地址
asp.netcoreidentity系列之三
在这节中我们将研究ASP.NETCoreIdentity中用户名、邮件、密码策略,解释一下Identity默认提供的策略以及如何实现自定义策略,最后我们针对用户名、邮件、密码实现客户自定义策略1、ASP.NETCoreIdentity密码策略ASP.NETCoreIdentity... 查看详情
asp.netcoreidentity系列之八
这一节我们主要介绍在ASP.NETCoreIdentity中使用策略进行授权,Policy是用户必须具备一组集合为授权访问应用程序上的资源。IdentityPolicy的授权可以包含对用户的Role和Claim,这有助于我们在应用程序中构建更丰富的授权结构... 查看详情
asp.netcoreidentity系列之七
在这节中我们主要介绍在ASP.NETCoreIdentity如何使用Claims,ASP.NETCoreIdentityClaims是颁发给用户键值对(name=value)表示用户允许做什么。例如,驾驶执照颁发机构给个人颁发驾驶执照,如果驾照上的DOB是1990年12月21日,... 查看详情
第16章使用asp.netcoreidentity(代码片段)
注意对于任何先决条件(例如模板),首先要查看概述。IdentityServer旨在提供灵活性,其中一部分允许您为用户及其数据(包括账户密码)使用所需的任何数据库。如果您从新的用户数据库开始,那么ASP.NETIdentity是您可以选择的... 查看详情
asp.netcore系列48identity身份模型自定义(代码片段)
原文:asp.netcore系列48Identity身份模型自定义一.概述 ASP.NETCoreIdentity提供了一个框架,用于管理和存储在ASP.NETCore应用中的用户帐户。 Identity添加到项目时单个用户帐户选择作为身份验证机制。 默认情况下,Identity可以使... 查看详情
asp.netcoremvc2.x全面教程_asp.netcoremvc14.asp.netcoreidentity入门
默认的身份认证好授权系统UserManager用来操作用户的类,Singi用来身份认证的添加AccountController先声明SignInManager和UserManager这两个服务快捷键Ctrl+.两个都需要分别进行Ctrl+.快速的生成创建登陆的ActionLogin建立View创建LoginViewModel主要... 查看详情
数据库设计系列之四--er图
逻辑设计是做什么?1、将需求转化为数据库的逻辑模型2、通过ER图的型式对逻辑模型进行展示3、同所选用的具体的DBMS系统无关 查看详情
快速掌握asp.net身份认证框架identity-通过邮件重置密码(代码片段)
这是ASP.NETCoreIdentity系列的第四篇文章,上一篇文章讲解了如何在ASP.NETCoreIdentity中实现用户登录与登出。这篇文章讲一讲如何在ASP.NETCoreIdentity中通过邮件服务实现用户账号的密码重置。点击上方或后方蓝字,阅读ASP.NETCore... 查看详情
mongo3.4分片集群系列之四:搭建分片集群--哈希分片+安全+区域
这个系列大致想跟大家分享以下篇章(我会持续更新的↖(^ω^)↗):1、mongo3.4分片集群系列之一:浅谈分片集群2、mongo3.4分片集群系列之二:搭建分片集群--哈希分片3、mongo3.4分片集群系列之三:搭建分片集群--哈希分片+安全4、... 查看详情
之四-总结
前文链接高可用系列文章之一-概述-东风微鸣技术博客(ewhisper.cn)高可用系列文章之二-传统分层架构技术方案-东风微鸣技术博客(ewhisper.cn)高可用系列文章之三-NGINX高可用实施方案-东风微鸣技术博客(ewhisper.c... 查看详情
如何覆盖 ASP.NET Core Identity 的密码策略
】如何覆盖ASP.NETCoreIdentity的密码策略【英文标题】:HowoverrideASP.NETCoreIdentity\'spasswordpolicy【发布时间】:2017-02-1101:05:41【问题描述】:默认情况下,ASP.NETCoreIdentity的密码策略要求至少有一个特殊字符、一个大写字母、一个数字... 查看详情
后端开发实践系列之四——简单可用的cqrs编码实践
本文只讲了一件事情:软件模型中存在读模型和写模型之分,CQRS便为此而生。20多年前,BertrandMeyer在他的《Object-OrientedSoftwareConstruction》一书中提出了CQS(CommandQuerySeperation,命令查询分离)的概念,指出:Everymethodshouldeitherbeacom... 查看详情
cartographer系列之四——地图文件导出
个人能力有限,若有错误请批评指正!转载请标明出处:http://www.cnblogs.com/wenhust/一、目的Cartographer是google的开源2DLaser-basedSLAM方案,可以直接在ROS上运行并建图(可参考之前的文章)。不过到目前为止,还没有提供可以直接保存... 查看详情
多线程系列之四:guardedsuspension模式(代码片段)
一,什么是GuardedSuspension模式如果执行现在的处理会造成问题,就让执行处理的线程等待。这种模式通过让线程等待来保证实例的安全性二,实现一个简单的线程间通信的例子一个线程(ClientThread)将请求(Request)的实例传递给另外... 查看详情
在 ASP.Net Core Identity 中刷新用户 cookie 票证
】在ASP.NetCoreIdentity中刷新用户cookie票证【英文标题】:RefreshusercookieticketinASP.NetCoreIdentity【发布时间】:2017-06-1117:43:04【问题描述】:在ASP.NETCoreWeb应用程序的控制器中,我想刷新用户并声明存储在客户端上的cookie票证。客户端... 查看详情
Asp.net core Identity “INSERT 语句与 FOREIGN KEY 约束冲突”
】Asp.netcoreIdentity“INSERT语句与FOREIGNKEY约束冲突”【英文标题】:Asp.netcoreIdentity"TheINSERTstatementconflictedwiththeFOREIGNKEYconstraint"【发布时间】:2017-05-0721:56:07【问题描述】:我使用ASP.NETCOREIdentity创建ASP.NETCORE应用程序。我创... 查看详情
docker系列教程之四dockerfile入门(代码片段)
在上一篇的文章中,我们把 Docker 容器的工作流程剖析的十分清楚了,我们大体可以知道 Docker 组件协作运行容器可以分为以下几个过程:Docker 客户端执行 dockerrun 命令Dockerdaemon 发现本地没有我们需... 查看详情
vue.js系列之四计算属性和观察者
一、计算属性1、模版内的表达式非常便利,但是设计它们的初衷是用于简单计算的。在模版中放入太多的逻辑运算会让模版过重且难以维护,例如如下代码:<divid="example">{{message.split(‘‘).reverse().join(‘‘)}}</div>在这个地方... 查看详情