ASP.NET Core Identity 详解ASP.NET Core 之 Identity 入门(二)

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

ASP.NET Core Identity 详解ASP.NET Core 之 Identity 入门(二)

Savorboard   2021-03-22 我要评论
想了解详解ASP.NET Core 之 Identity 入门(二)的相关内容吗,Savorboard在本文为您仔细讲解ASP.NET Core Identity 的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:.net,core,identity,asp.net,identity入门,.net,core,identity,ef,下面大家一起来学习吧。

前言

在https://m.qb5200.com/上篇文章 中讲了关于https://m.qb5200.com/Identityhttps://m.qb5200.com/需要了解的单词以及相对应的几个知识点,并且知道了Identity处在整个登入流程中的位置,本篇主要是在https://m.qb5200.com/.NEThttps://m.qb5200.com/整个认证系统中比较重要的一个环节,就是https://m.qb5200.com/认证(Authentication),因为想要把https://m.qb5200.com/Identityhttps://m.qb5200.com/讲清楚,是绕不过https://m.qb5200.com/Authenticationhttps://m.qb5200.com/的。

其实https://m.qb5200.com/Identityhttps://m.qb5200.com/也是认证系统的一个具体使用,大家一定要把https://m.qb5200.com/Authenticationhttps://m.qb5200.com/和https://m.qb5200.com/Identityhttps://m.qb5200.com/当作是两个东西,一旦混淆,你就容易陷入进去。

下面就来说一下https://m.qb5200.com/ASP.NEThttps://m.qb5200.com/Corehttps://m.qb5200.com/中的认证系统是怎么样一回事。不要怕,其实很简单,全是干货~

Gettinghttps://m.qb5200.com/Started

大家应该还记得在上一篇中的奥巴马先生吧,他现在不住在华盛顿了,他到中国来旅游了,现在住在北京,这几天听说西湖风景不错,于是在https://m.qb5200.com/12306https://m.qb5200.com/定了一张北京到杭州的高铁票。取到票之后,他向我们展示了一下:

今天是11.11号,奥巴马很开心,原因你懂的。快到出发的时间了,于是,拿着票走到了火车站检票口,刚把SFZ和火车票递给检票员。“cut”,导演喊了一声。尼玛原来是在拍电影呢~

导演说:奥巴马,你演的太烂了,别演了,你来演检票员吧,让旁边小李来演要出行路由的奥巴马吧。奥巴马不情愿的说了一声:“好吧,希望小李能够受的了你”。

“action”,导演又喊了一声,故事开始了~

AuthenticationManager

奥巴马当了检票员以后,特别高兴,因为他有权利了呀,他可以控制别人能不能上车了,说不定还能偷偷放几个人进去捞点外快呢。

得知了他能干什么以后,他觉得检票员这个名字简直太https://m.qb5200.com/lowhttps://m.qb5200.com/了,很快,他就有了一个新的高大上的名字,叫:认证管理员(AuthenticationManager),而且,他觉得他自己应该处在整个核心位置,为什么呢?你想想看,那么庞大的一套铁路载人系统,能不能有收入有钱赚,全靠他给不给放人进去,如果一个人都不放进去,另外那一大帮人只能去喝西北风了。

到这里,聪明的同学可能已经知道奥巴马把他自己放在怎么样一个核心位置了。对,他把自己放到了https://m.qb5200.com/HttpContexthttps://m.qb5200.com/里面。怎么样?https://m.qb5200.com/够核心吧。

这里延伸第一个知识点:AuthenticationManagerhttps://m.qb5200.com/所处的位置

有同学在上面的截图里面发现了https://m.qb5200.com/publichttps://m.qb5200.com/abstracthttps://m.qb5200.com/ClaimsPrincipalhttps://m.qb5200.com/Userhttps://m.qb5200.com/{https://m.qb5200.com/get;https://m.qb5200.com/set;https://m.qb5200.com/},https://m.qb5200.com/这不就是我们上一篇中讲到的https://m.qb5200.com/“https://m.qb5200.com/证件当事人https://m.qb5200.com/”https://m.qb5200.com/,现在小李扮演的那个角色么?https://m.qb5200.com/对,这个https://m.qb5200.com/Userhttps://m.qb5200.com/就是本文中的小李,被你提前发现他躲着这里了,嘿嘿。

还有一个知识点,就是https://m.qb5200.com/AuthenticationScheme,什么意思呢?https://m.qb5200.com/且看  奥巴马敢把自己放在这么核心的位置也是有他的能力的,怎么讲呢?https://m.qb5200.com/比如说在检票的时候,别人递过来一张SFZ和一张火车票,那怎么样验证这两个证件是合法的呢?https://m.qb5200.com/以下就是奥巴马提出的针对两种证件的验证方案:

方案1、针对SFZ的验证,可以查看其本人是否和SFZ头像是否一致,年龄是否符合当事人具体年龄。

方案2、针对火车票的验证,可以看车次,时间是否符合发车目标,另外可以看车票上的身份号码是否和SFZ一致。

其中,这每一种方案,就对应一个https://m.qb5200.com/AuthenticationScheme(验证方案名称),是不是明白了。

这就是第二个知识点https://m.qb5200.com/AuthenticationSchemehttps://m.qb5200.com/很重要。

知道了奥巴马的职责后,就很容易的把代码写出来了:

publichttps://m.qb5200.com/abstracthttps://m.qb5200.com/classhttps://m.qb5200.com/AuthenticationManager { https://m.qb5200.com/https://m.qb5200.com///AuthenticateContext包含了需要认证的上下文,里面就有小李 https://m.qb5200.com/https://m.qb5200.com/publichttps://m.qb5200.com/abstracthttps://m.qb5200.com/Taskhttps://m.qb5200.com/AuthenticateAsync(AuthenticateContexthttps://m.qb5200.com/context); https://m.qb5200.com/https://m.qb5200.com/ https://m.qb5200.com/https://m.qb5200.com///握手 https://m.qb5200.com/https://m.qb5200.com/publichttps://m.qb5200.com/abstracthttps://m.qb5200.com/Taskhttps://m.qb5200.com/ChallengeAsync(stringhttps://m.qb5200.com/authenticationScheme,https://m.qb5200.com/AuthenticationPropertieshttps://m.qb5200.com/properties,https://m.qb5200.com/ChallengeBehaviorhttps://m.qb5200.com/behavior); https://m.qb5200.com/https://m.qb5200.com/ https://m.qb5200.com/https://m.qb5200.com///登入 https://m.qb5200.com/https://m.qb5200.com/publichttps://m.qb5200.com/abstracthttps://m.qb5200.com/Taskhttps://m.qb5200.com/SignInAsync(stringhttps://m.qb5200.com/authenticationScheme,https://m.qb5200.com/ClaimsPrincipalhttps://m.qb5200.com/principal,https://m.qb5200.com/AuthenticationPropertieshttps://m.qb5200.com/properties); https://m.qb5200.com/https://m.qb5200.com/ https://m.qb5200.com/https://m.qb5200.com///登出 https://m.qb5200.com/https://m.qb5200.com/publichttps://m.qb5200.com/abstracthttps://m.qb5200.com/Taskhttps://m.qb5200.com/SignOutAsync(stringhttps://m.qb5200.com/authenticationScheme,https://m.qb5200.com/AuthenticationPropertieshttps://m.qb5200.com/properties); }

奥巴马做为一个检票员,有一个认证方法,AuthenticateAsync()https://m.qb5200.com/,注意这是其一个核心功能,其他几个都可以没有,但是唯独不能没有这个功能,没有的话他就不能称之为一个检票员了。

然后还有一个握手ChallengeAsync,登入SignInAsync和登出SignOutAsync,下面说说笔者对这三个方法的理解吧。

ChallengeAsync:是社区协议文件https://m.qb5200.com/RFC2167https://m.qb5200.com/定义的关于在HTTPhttps://m.qb5200.com/Authenticationhttps://m.qb5200.com/过程中的一种关于握手的一个过程,主要是摘要认证(digesthttps://m.qb5200.com/authentication)。

是不是有点专业,看不懂,没事,有通俗版本的。https://m.qb5200.com/小李要进站了,这个时候小李问了一下我们的检票员奥巴马先生。

    https://m.qb5200.com/https://m.qb5200.com/
  1. 小李:“你好,检票员,我可以进站吗?”
  2. https://m.qb5200.com/https://m.qb5200.com/
  3. 检票员奥巴马:“要赶火车吗?可以啊,请出示你的证件?”
  4. https://m.qb5200.com/https://m.qb5200.com/
  5. 小李:“好的,这是我的证件,你检查一下?”
  6. https://m.qb5200.com/https://m.qb5200.com/
  7. 检票员奥巴马:“嗯,证件没问题,进去吧”

这样一个过程就是握手(digest-challenge)或者叫问答的一个过程,明白了https://m.qb5200.com/ChallengeAsynchttps://m.qb5200.com/的原理了吧?https://m.qb5200.com/是不是很简单。

SignInAsync,SignOutAsync:个人觉得这两个不应该放在这里,因为并不属于认证的职责,也不属于协议规定的内容。但是这两个方法确实需要抽象,应该单独抽取一个接口存放,至于为什么这样做,或许是因为以下原因:

1、对登入登出的抽象是和认证紧密结合的,大多数情况下认证资料的保存是需要在SignIn进行的,比如https://m.qb5200.com/Cookieshttps://m.qb5200.com/Authenticationhttps://m.qb5200.com/中间件就在SignIn方法里面做了Cookie的保存。

2、https://m.qb5200.com/AuthenticationManagerhttps://m.qb5200.com/这个对象是处在https://m.qb5200.com/HttpContext

上下文里面的,本着面向抽象和封装的原则,放到其里面是合适的,这样能够很方便的用户对其调用。

关于https://m.qb5200.com/AuthenticationManagerhttps://m.qb5200.com/已经介绍完了,是不是很简单呢?

IAuthenticationHandler

有些同学可能会问了,如果https://m.qb5200.com/AuthenticationManagerhttps://m.qb5200.com/不提供接口的话,只是一个抽象类的话,那如果自定义认证方法就必须继承它,这对于开发者来说是不友好的,也违背了面向接口编程的理念。嗯,确实是这样,那么接口来了:

publichttps://m.qb5200.com/interfacehttps://m.qb5200.com/IAuthenticationHandler { https://m.qb5200.com/https://m.qb5200.com/voidhttps://m.qb5200.com/GetDescriptions(DescribeSchemesContexthttps://m.qb5200.com/context); https://m.qb5200.com/https://m.qb5200.com/Taskhttps://m.qb5200.com/AuthenticateAsync(AuthenticateContexthttps://m.qb5200.com/context); https://m.qb5200.com/https://m.qb5200.com/Taskhttps://m.qb5200.com/ChallengeAsync(ChallengeContexthttps://m.qb5200.com/context); https://m.qb5200.com/https://m.qb5200.com/Taskhttps://m.qb5200.com/SignInAsync(SignInContexthttps://m.qb5200.com/context); https://m.qb5200.com/https://m.qb5200.com/Taskhttps://m.qb5200.com/SignOutAsync(SignOutContexthttps://m.qb5200.com/context); }

这个接口是在https://m.qb5200.com/AuthenticationManagerhttps://m.qb5200.com/实现类https://m.qb5200.com/DefaultAuthenticationManagerhttps://m.qb5200.com/中延伸出来的,所以大家不用再去看里面的源码了,记住以后如果需要重写认证相关的东西,实现IAuthenticationHandler就可以了。

Authenticationhttps://m.qb5200.com/中间件

对https://m.qb5200.com/IAuthenticationHandlerhttps://m.qb5200.com/的初步实现,封装了https://m.qb5200.com/AuthenticationHandlerhttps://m.qb5200.com/这个抽象类,把具体的核心功能都交给下游去实现了,下面的CookieAuthenticationhttps://m.qb5200.com/中间件核心类https://m.qb5200.com/CookieAuthenticationHandlerhttps://m.qb5200.com/就是继承自AuthenticationHandler,https://m.qb5200.com/知道这么多就够了。

CookieAuthenticationhttps://m.qb5200.com/中间件

故事还要继续,奥巴马在接到小李递来的SFZ和火车票之后,首先拿着火车票在一个二维码机器上扫描了一下,然后又拿着SFZ在一个机器上刷了一下,经过核查,发现都没有问题。于是拿起印章在上面盖了一个https://m.qb5200.com/“https://m.qb5200.com/验讫https://m.qb5200.com/”。

这中间都发生了什么呢?

首先,在二维码扫描的过程,这个过程二维码机器会解析你火车票上的二维码,如果发现解析失败,会直接响应认证失败。也就是你别想进站了。

如果解析成功,就会得到你这个票据中的信息了,然后拿到你票据里面的的当事人信息进行验证是否被列为了铁路局黑名单中。

如果验证通过,则会给你颁发一个识别码,把符合你身份的一个识别码写入到你的火车票中和检票员旁边的电脑系统中,即https://m.qb5200.com/“https://m.qb5200.com/验讫https://m.qb5200.com/”。

话说这个验讫有点高级,它会向你的火车票芯片中写入一些信息,那么都写入些什么信息呢?https://m.qb5200.com/1、奥巴马个人的信息。2、验证途中的一些上下信息。3、使用的验证方案。

知道了,这些之后,那么就很容易实现这个验证方法了,对吧?https://m.qb5200.com/以下是https://m.qb5200.com/CookieAuthenticationhttps://m.qb5200.com/中间件中的核心类https://m.qb5200.com/CookieAuthenticationHandlerhttps://m.qb5200.com/的里面的核心方法HandleAuthenticateAsync(),同样你可以理解为实现的https://m.qb5200.com/IAuthenticationHandlerhttps://m.qb5200.com/接口的https://m.qb5200.com/AuthenticateAsync:

protectedhttps://m.qb5200.com/overridehttps://m.qb5200.com/asynchttps://m.qb5200.com/Task<AuthenticateResult>https://m.qb5200.com/HandleAuthenticateAsync() { https://m.qb5200.com/https://m.qb5200.com///https://m.qb5200.com/解析二维码 https://m.qb5200.com/https://m.qb5200.com/varhttps://m.qb5200.com/resulthttps://m.qb5200.com/=https://m.qb5200.com/awaithttps://m.qb5200.com/EnsureCookieTicket(); https://m.qb5200.com/https://m.qb5200.com/ifhttps://m.qb5200.com/(!result.Succeeded) https://m.qb5200.com/https://m.qb5200.com/{ https://m.qb5200.com/https://m.qb5200.com/https://m.qb5200.com/https://m.qb5200.com/returnhttps://m.qb5200.com/result; https://m.qb5200.com/https://m.qb5200.com/} https://m.qb5200.com/https://m.qb5200.com///https://m.qb5200.com/从二维码中拿当事人信息进行验证 https://m.qb5200.com/https://m.qb5200.com/varhttps://m.qb5200.com/contexthttps://m.qb5200.com/=https://m.qb5200.com/newhttps://m.qb5200.com/CookieValidatePrincipalContext(Context,https://m.qb5200.com/result.Ticket,https://m.qb5200.com/Options); https://m.qb5200.com/https://m.qb5200.com/awaithttps://m.qb5200.com/Options.Events.ValidatePrincipal(context); https://m.qb5200.com/https://m.qb5200.com/ifhttps://m.qb5200.com/(context.Principalhttps://m.qb5200.com/==https://m.qb5200.com/null) https://m.qb5200.com/https://m.qb5200.com/{ https://m.qb5200.com/https://m.qb5200.com/https://m.qb5200.com/https://m.qb5200.com/returnhttps://m.qb5200.com/AuthenticateResult.Fail("Nohttps://m.qb5200.com/principal."); https://m.qb5200.com/https://m.qb5200.com/} https://m.qb5200.com/https://m.qb5200.com/ifhttps://m.qb5200.com/(context.ShouldRenew) https://m.qb5200.com/https://m.qb5200.com/{ https://m.qb5200.com/https://m.qb5200.com/https://m.qb5200.com/https://m.qb5200.com/RequestRefresh(result.Ticket); https://m.qb5200.com/https://m.qb5200.com/} https://m.qb5200.com/https://m.qb5200.com/ https://m.qb5200.com/https://m.qb5200.com///https://m.qb5200.com/验讫,https://m.qb5200.com/写入芯片 https://m.qb5200.com/https://m.qb5200.com/returnhttps://m.qb5200.com/AuthenticateResult.Success(newhttps://m.qb5200.com/AuthenticationTicket(context.Principal,https://m.qb5200.com/context.Properties,https://m.qb5200.com/Options.AuthenticationScheme)); }

HandleSignInAsync

我们故事继续……

奥巴马检票完成之后,把票就交给了小李,小李拿到票之后,导演又喊了一声:“https://m.qb5200.com/cuthttps://m.qb5200.com/”……

怎么又停了,小李和奥巴马一肚子的疑惑,导演说:“https://m.qb5200.com/奥巴马呀,你检票员演的不错,还是继续扮演你的本职角色吧,演好了中午盒饭给你双份,小李,你来演检票员吧https://m.qb5200.com/”。  可以吃两份盒饭了,奥巴马听后心里还是很开心。

“action”https://m.qb5200.com/导演喊了一声……

奥巴马接过票,向着车站里面的列车停车处走去,走到了列车门口要进去的时候,又出现了一个人,奥巴马知道,这个人就是做车内乘客登记的(ps:https://m.qb5200.com/一般情况下,做乘客登记都是在列车行驶的过程中,在这里我们假设这个做乘客登记的人比较勤快,就在车门口守着),登记完成之后就让奥巴马进去了。

那么,登记这个过程中都干了些什么呢?

首先,登记员的手持设备会解析火车票票里面写入芯片中的信息,发现没有问题,就开始向自己手里面的登记本登记信息了,主要包含车票主人信息,过期时间,审核人等。

这样整个过程就是https://m.qb5200.com/HandleSignInAsynchttps://m.qb5200.com/的一个过程,换成程序术语就是,组装https://m.qb5200.com/Cookiehttps://m.qb5200.com/登入上下文信息,写入到https://m.qb5200.com/Httphttps://m.qb5200.com/流的https://m.qb5200.com/headerhttps://m.qb5200.com/中,也就写入到了客户端浏览器cookie。

至此,整个过程就完了,我们来看一下代码:

//方法里面的流程,我只列出了核心部分,影响阅读的全删了 protectedhttps://m.qb5200.com/overridehttps://m.qb5200.com/asynchttps://m.qb5200.com/Taskhttps://m.qb5200.com/HandleSignInAsync(SignInContexthttps://m.qb5200.com/signin) { https://m.qb5200.com/https://m.qb5200.com///https://m.qb5200.com/解析芯片中的信息 https://m.qb5200.com/https://m.qb5200.com/varhttps://m.qb5200.com/resulthttps://m.qb5200.com/=https://m.qb5200.com/awaithttps://m.qb5200.com/EnsureCookieTicket(); https://m.qb5200.com/https://m.qb5200.com/ https://m.qb5200.com/https://m.qb5200.com///https://m.qb5200.com/组织登入上下文,设置过期时间等 https://m.qb5200.com/https://m.qb5200.com///https://m.qb5200.com/使用https://m.qb5200.com/datahttps://m.qb5200.com/protectedhttps://m.qb5200.com/加密登记本上的信息 https://m.qb5200.com/https://m.qb5200.com/varhttps://m.qb5200.com/cookieValuehttps://m.qb5200.com/=https://m.qb5200.com/Options.TicketDataFormat.Protect(ticket); https://m.qb5200.com/https://m.qb5200.com///https://m.qb5200.com/写入到浏览器header https://m.qb5200.com/https://m.qb5200.com/awaithttps://m.qb5200.com/ApplyHeaders(cookieValue); }

不想深入了解的可以忽略这部分内容:

在https://m.qb5200.com/HandleSignInAsynchttps://m.qb5200.com/这个函数的源码中,其中有一个很巧妙的设计,https://m.qb5200.com/就是https://m.qb5200.com/awaithttps://m.qb5200.com/Options.Events.SignedIn(signedInContext);https://m.qb5200.com/这样一句代码,干什么用的呢?https://m.qb5200.com/而且前后一共调用了两次,有同学知道是为什么吗?https://m.qb5200.com/我准备在下一篇中给出答案。

还记得前面https://m.qb5200.com/HttpContexthttps://m.qb5200.com/中的ClaimsPrincipalhttps://m.qb5200.com/User吗?https://m.qb5200.com/就是小李临时顶替的那个角色,现在有值了,他就是是奥巴马了。

奥巴马在座位上坐好之后,经过6个小时的路程就从北京到杭州了,不得不佩服中国高铁的速度呀,在欣赏晚西湖的风景后,奥巴马给我们传来了一张照片:

至此,CookieAuthenticationhttps://m.qb5200.com/中间件的整个工作流程已经讲完了,故事也结束了。

以上,就是这两行代码背后的故事:

varhttps://m.qb5200.com/userhttps://m.qb5200.com/=https://m.qb5200.com/newhttps://m.qb5200.com/ClaimsPrincipal(newhttps://m.qb5200.com/ClaimsIdentity(new[]https://m.qb5200.com/{https://m.qb5200.com/newhttps://m.qb5200.com/Claim(ClaimTypes.Name,https://m.qb5200.com/"奥巴马")https://m.qb5200.com/},https://m.qb5200.com/CookieAuthenticationDefaults.AuthenticationScheme)); awaithttps://m.qb5200.com/HttpContext.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,https://m.qb5200.com/user);

总结

在本篇中我们知道了https://m.qb5200.com/AuthenticationManager,也知道了https://m.qb5200.com/IAuthenticationHandlerhttps://m.qb5200.com/并且简单的介绍了一下https://m.qb5200.com/Authenticationhttps://m.qb5200.com/中间件和https://m.qb5200.com/CookieAuthenticationhttps://m.qb5200.com/中间件,其中https://m.qb5200.com/CookieAuthenticationhttps://m.qb5200.com/中间件是我们以后使用最多的一个中间件了,本篇也对其做了一个详细的介绍,我想通过本篇文章在以后使用的过程中应该问题不大了。

有同学可能会问了,讲了这么多认证的东西它和https://m.qb5200.com/Identityhttps://m.qb5200.com/有什么关系呢?https://m.qb5200.com/难道我通篇都在隐藏他和https://m.qb5200.com/Identityhttps://m.qb5200.com/的关系你没看出来?。。。。真的想知道?https://m.qb5200.com/看下一篇吧。

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们