- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解ASP.NET Core 之 Identity 入门(二)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
在 上篇文章 中讲了关于 Identity 需要了解的单词以及相对应的几个知识点,并且知道了Identity处在整个登入流程中的位置,本篇主要是在 .NET 整个认证系统中比较重要的一个环节,就是 认证(Authentication),因为想要把 Identity 讲清楚,是绕不过 Authentication 的.
其实 Identity 也是认证系统的一个具体使用,大家一定要把 Authentication 和 Identity 当作是两个东西,一旦混淆,你就容易陷入进去.
下面就来说一下 ASP.NET Core 中的认证系统是怎么样一回事。不要怕,其实很简单,全是干货~ 。
Getting Started 。
大家应该还记得在上一篇中的奥巴马先生吧,他现在不住在华盛顿了,他到中国来旅游了,现在住在北京,这几天听说西湖风景不错,于是在 12306 定了一张北京到杭州的高铁票。取到票之后,他向我们展示了一下:
今天是11.11号,奥巴马很开心,原因你懂的。快到出发的时间了,于是,拿着票走到了火车站检票口,刚把身份证和火车票递给检票员。“cut”,导演喊了一声。尼玛原来是在拍电影呢~ 。
导演说:奥巴马,你演的太烂了,别演了,你来演检票员吧,让旁边小李来演要出行路由的奥巴马吧。奥巴马不情愿的说了一声:“好吧,希望小李能够受的了你”.
“action”,导演又喊了一声,故事开始了~ 。
AuthenticationManager 。
奥巴马当了检票员以后,特别高兴,因为他有权利了呀,他可以控制别人能不能上车了,说不定还能偷偷放几个人进去捞点外快呢.
得知了他能干什么以后,他觉得检票员这个名字简直太 low 了,很快,他就有了一个新的高大上的名字,叫:认证管理员(AuthenticationManager),而且,他觉得他自己应该处在整个核心位置,为什么呢?你想想看,那么庞大的一套铁路载人系统,能不能有收入有钱赚,全靠他给不给放人进去,如果一个人都不放进去,另外那一大帮人只能去喝西北风了.
到这里,聪明的同学可能已经知道奥巴马把他自己放在怎么样一个核心位置了。对,他把自己放到了 HttpContext 里面。怎么样? 够核心吧.
这里延伸第一个知识点:AuthenticationManager 所处的位置 。
有同学在上面的截图里面发现了 public abstract ClaimsPrincipal User { get; set; }, 这不就是我们上一篇中讲到的 “ 证件当事人 ” ,现在小李扮演的那个角色么? 对,这个 User 就是本文中的小李,被你提前发现他躲着这里了,嘿嘿.
还有一个知识点,就是 AuthenticationScheme,什么意思呢? 且看 奥巴马敢把自己放在这么核心的位置也是有他的能力的,怎么讲呢? 比如说在检票的时候,别人递过来一张身份证和一张火车票,那怎么样验证这两个证件是合法的呢? 以下就是奥巴马提出的针对两种证件的验证方案:
方案1、针对身份证的验证,可以查看其本人是否和身份证头像是否一致,年龄是否符合当事人具体年龄.
方案2、针对火车票的验证,可以看车次,时间是否符合发车目标,另外可以看车票上的身份号码是否和身份证一致.
其中,这每一种方案,就对应一个 AuthenticationScheme(验证方案名称),是不是明白了.
这就是第二个知识点 AuthenticationScheme 很重要.
知道了奥巴马的职责后,就很容易的把代码写出来了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
abstract
class
AuthenticationManager
{
//AuthenticateContext包含了需要认证的上下文,里面就有小李
public
abstract
Task AuthenticateAsync(AuthenticateContext context);
//握手
public
abstract
Task ChallengeAsync(
string
authenticationScheme, AuthenticationProperties properties, ChallengeBehavior behavior);
//登入
public
abstract
Task SignInAsync(
string
authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties);
//登出
public
abstract
Task SignOutAsync(
string
authenticationScheme, AuthenticationProperties properties);
}
|
奥巴马做为一个检票员,有一个认证方法,AuthenticateAsync() ,注意这是其一个核心功能,其他几个都可以没有,但是唯独不能没有这个功能,没有的话他就不能称之为一个检票员了.
然后还有一个握手ChallengeAsync,登入SignInAsync和登出SignOutAsync,下面说说笔者对这三个方法的理解吧.
ChallengeAsync:是社区协议文件 RFC2167 定义的关于在HTTP Authentication 过程中的一种关于握手的一个过程,主要是摘要认证(digest authentication).
是不是有点专业,看不懂,没事,有通俗版本的。 小李要进站了,这个时候小李问了一下我们的检票员奥巴马先生.
这样一个过程就是握手(digest-challenge)或者叫问答的一个过程,明白了 ChallengeAsync 的原理了吧? 是不是很简单.
SignInAsync,SignOutAsync:个人觉得这两个不应该放在这里,因为并不属于认证的职责,也不属于协议规定的内容。但是这两个方法确实需要抽象,应该单独抽取一个接口存放,至于为什么这样做,或许是因为以下原因:
1、对登入登出的抽象是和认证紧密结合的,大多数情况下认证资料的保存是需要在SignIn进行的,比如 Cookies Authentication 中间件就在SignIn方法里面做了Cookie的保存.
2、 AuthenticationManager 这个对象是处在 HttpContext 。
上下文里面的,本着面向抽象和封装的原则,放到其里面是合适的,这样能够很方便的用户对其调用.
关于 AuthenticationManager 已经介绍完了,是不是很简单呢?
IAuthenticationHandler 。
有些同学可能会问了,如果 AuthenticationManager 不提供接口的话,只是一个抽象类的话,那如果自定义认证方法就必须继承它,这对于开发者来说是不友好的,也违背了面向接口编程的理念。嗯,确实是这样,那么接口来了:
1
2
3
4
5
6
7
8
9
10
11
12
|
public
interface
IAuthenticationHandler
{
void
GetDescriptions(DescribeSchemesContext context);
Task AuthenticateAsync(AuthenticateContext context);
Task ChallengeAsync(ChallengeContext context);
Task SignInAsync(SignInContext context);
Task SignOutAsync(SignOutContext context);
}
|
这个接口是在 AuthenticationManager 实现类 DefaultAuthenticationManager 中延伸出来的,所以大家不用再去看里面的源码了,记住以后如果需要重写认证相关的东西,实现IAuthenticationHandler就可以了.
Authentication 中间件 。
对 IAuthenticationHandler 的初步实现,封装了 AuthenticationHandler 这个抽象类,把具体的核心功能都交给下游去实现了,下面的CookieAuthentication 中间件核心类 CookieAuthenticationHandler 就是继承自AuthenticationHandler, 知道这么多就够了.
CookieAuthentication 中间件 。
故事还要继续,奥巴马在接到小李递来的身份证和火车票之后,首先拿着火车票在一个二维码机器上扫描了一下,然后又拿着身份证在一个机器上刷了一下,经过核查,发现都没有问题。于是拿起印章在上面盖了一个 “ 验讫 ”.
这中间都发生了什么呢?
首先,在二维码扫描的过程,这个过程二维码机器会解析你火车票上的二维码,如果发现解析失败,会直接响应认证失败。也就是你别想进站了.
如果解析成功,就会得到你这个票据中的信息了,然后拿到你票据里面的的当事人信息进行验证是否被列为了铁路局黑名单中.
如果验证通过,则会给你颁发一个识别码,把符合你身份的一个识别码写入到你的火车票中和检票员旁边的电脑系统中,即 “ 验讫 ”.
话说这个验讫有点高级,它会向你的火车票芯片中写入一些信息,那么都写入些什么信息呢? 1、奥巴马个人的信息。2、验证途中的一些上下信息。3、使用的验证方案.
知道了,这些之后,那么就很容易实现这个验证方法了,对吧? 以下是 CookieAuthentication 中间件中的核心类 CookieAuthenticationHandler 的里面的核心方法HandleAuthenticateAsync(),同样你可以理解为实现的 IAuthenticationHandler 接口的 AuthenticateAsync:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
protected
override
async Task<AuthenticateResult> HandleAuthenticateAsync()
{
// 解析二维码
var result = await EnsureCookieTicket();
if
(!result.Succeeded)
{
return
result;
}
// 从二维码中拿当事人信息进行验证
var context =
new
CookieValidatePrincipalContext(Context, result.Ticket, Options);
await Options.Events.ValidatePrincipal(context);
if
(context.Principal ==
null
)
{
return
AuthenticateResult.Fail(
"No principal."
);
}
if
(context.ShouldRenew)
{
RequestRefresh(result.Ticket);
}
// 验讫, 写入芯片
return
AuthenticateResult.Success(
new
AuthenticationTicket(context.Principal, context.Properties, Options.AuthenticationScheme));
}
|
HandleSignInAsync 。
我们故事继续…… 。
奥巴马检票完成之后,把票就交给了小李,小李拿到票之后,导演又喊了一声:“ cut ”…… 。
怎么又停了,小李和奥巴马一肚子的疑惑,导演说:“ 奥巴马呀,你检票员演的不错,还是继续扮演你的本职角色吧,演好了中午盒饭给你双份,小李,你来演检票员吧 ”。 可以吃两份盒饭了,奥巴马听后心里还是很开心.
“action” 导演喊了一声…… 。
奥巴马接过票,向着车站里面的列车停车处走去,走到了列车门口要进去的时候,又出现了一个人,奥巴马知道,这个人就是做车内乘客登记的(ps: 一般情况下,做乘客登记都是在列车行驶的过程中,在这里我们假设这个做乘客登记的人比较勤快,就在车门口守着),登记完成之后就让奥巴马进去了.
那么,登记这个过程中都干了些什么呢?
首先,登记员的手持设备会解析火车票票里面写入芯片中的信息,发现没有问题,就开始向自己手里面的登记本登记信息了,主要包含车票主人信息,过期时间,审核人等.
这样整个过程就是 HandleSignInAsync 的一个过程,换成程序术语就是,组装 Cookie 登入上下文信息,写入到 Http 流的 header 中,也就写入到了客户端浏览器cookie.
至此,整个过程就完了,我们来看一下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//方法里面的流程,我只列出了核心部分,影响阅读的全删了
protected
override
async Task HandleSignInAsync(SignInContext signin)
{
// 解析芯片中的信息
var result = await EnsureCookieTicket();
// 组织登入上下文,设置过期时间等
// 使用 data protected 加密登记本上的信息
var cookieValue = Options.TicketDataFormat.Protect(ticket);
// 写入到浏览器header
await ApplyHeaders(cookieValue);
}
|
不想深入了解的可以忽略这部分内容:
在 HandleSignInAsync 这个函数的源码中,其中有一个很巧妙的设计, 就是 await Options.Events.SignedIn(signedInContext); 这样一句代码,干什么用的呢? 而且前后一共调用了两次,有同学知道是为什么吗? 我准备在下一篇中给出答案.
还记得前面 HttpContext 中的ClaimsPrincipal User吗? 就是小李临时顶替的那个角色,现在有值了,他就是是奥巴马了.
奥巴马在座位上坐好之后,经过6个小时的路程就从北京到杭州了,不得不佩服中国高铁的速度呀,在欣赏晚西湖的风景后,奥巴马给我们传来了一张照片:
至此,CookieAuthentication 中间件的整个工作流程已经讲完了,故事也结束了.
以上,就是这两行代码背后的故事:
1
2
|
var user =
new
ClaimsPrincipal(
new
ClaimsIdentity(
new
[] {
new
Claim(ClaimTypes.Name,
"奥巴马"
) }, CookieAuthenticationDefaults.AuthenticationScheme));
await HttpContext.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user);
|
总结 。
在本篇中我们知道了 AuthenticationManager,也知道了 IAuthenticationHandler 并且简单的介绍了一下 Authentication 中间件和 CookieAuthentication 中间件,其中 CookieAuthentication 中间件是我们以后使用最多的一个中间件了,本篇也对其做了一个详细的介绍,我想通过本篇文章在以后使用的过程中应该问题不大了.
有同学可能会问了,讲了这么多认证的东西它和 Identity 有什么关系呢? 难道我通篇都在隐藏他和 Identity 的关系你没看出来?。。。。真的想知道? 看下一篇吧.
原文链接:http://www.cnblogs.com/savorboard/p/aspnetcore-identity2.html 。
最后此篇关于详解ASP.NET Core 之 Identity 入门(二)的文章就讲到这里了,如果你想了解更多关于详解ASP.NET Core 之 Identity 入门(二)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
主要思想是将 EF Core nuget 包添加到 .NET Core 库项目,然后在一堆应用程序(例如 ASP.NET Core、Win 服务、控制台应用程序)中使用该库,而无需在每个应用程序中配置
我想要实现的是编写一个简单的.net核心后台工作程序(.net core 3.1)的代码,在该工作程序作为Windows服务运行时,我在其中将数据写入SQL Server数据库(通过EF Core 3
关于 .Net Core SDK download page 二进制文件有什么用?它与安装程序有何不同? 最佳答案 二进制文件是 .NET Core 的编译代码。它们拥有运行 .NET Core 所需
.NET Core 和 Entity Framework Core 之间的区别?我们可以在 .NET Core 中使用 Entity Framework Core 吗?两者都有什么优势? 最佳答案 E
.NET Core 和 ASP.NET Core 到底有什么区别? 它们是相互排斥的吗?我听说 ASP.NET Core 是基于 .NET Core 构建的,但它也可以基于完整的 .NET 框架构建。
我对 ASP.NET Core 开发完全陌生。我正在尝试使用单个模型和 mysql 创建一个简单的 asp.net core Web api 来存储模型数据,然后我想使用 Swagger 将其作为 R
.NET Core 和 Entity Framework Core 之间的区别?我们可以在 .NET Core 中使用 Entity Framework Core 吗?两者都有什么优势? 最佳答案 E
好吧,作为一个新的 .net 开发生态系统,我有点迷失在核心工具、版本等方面。 有人可以解释我之间的区别吗 VS 2015 核心工具预览版 x - See here .NET Core/SDK 与否
我已阅读有关如何通过信号器核心集线器从后台服务向客户端发送通知的文档。如何从客户端接收到后台服务的通知? 后台服务应该只是一个单例。 public class Startup { public
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 4年前关闭。 Improve t
非常简单的问题: 我正在尝试创建一个像这样的谓词构建器: var predicate = PredicateBuilder.False(); 但似乎在Net Core和EF Core中不可用。
在 .NET Core 自包含应用程序 中...我们需要在 project.json 中指定运行时 (RID) 我们希望我们的应用程序针对...发布为什么会这样? .NET Core 是跨平台的,与我
如何用 iCloud Core Data 替换我现有的 Core Data?这是我的持久商店协调员: lazy var persistentStoreCoordinator: NSPersistent
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 2 年前。 Improv
今天我正在学习新的 ASP.net 核心 API 3.1,我想将我的旧网站从 MVC4 转移到 Web API。除了一件事,一切都很好。数据库连接。在我的旧网站中,我为每个客户端(10/15 数据库)
我在 Visual Studio 2015 Update 3 和 .NET Core 1.0 中工作。我有一个 .NETCoreApp v1.0 类型的 Web API 项目。当我添加一个 .NET
我一直在尝试遵循 Ben Cull ( http://benjii.me/2016/06/entity-framework-core-migrations-for-class-library-proj
当我打开我的 vs 代码程序时,我收到以下消息: 无法找到 .NET Core SDK。 .NET Core 调试将不会启用。确保 .NET Core SDK 已安装并且在路径上。 如果我安装甚至卸载
我偶然发现了一个非常奇怪的问题。每当 Web 应用程序启动时,dotnet.exe 都会使用相当多的内存(大约 300M)。然而,当它触及某些部分时(我感觉这与 EF Core 使用有关),它会在短时
ASP.NET Core Web (.NET Core) 与 ASP.NET Core Web (.NET Framework) 有什么区别? .NET Framework 是否提供 similar
我是一名优秀的程序员,十分优秀!