ASP.NET Core Identity 实战(3)认证过程

如果你没接触过旧版Asp.Net Mvc中的 Authorize 或者 Cookie登陆,那么你一定会疑惑 认证这个名词,这太正式了,这到底代表这什么?

获取资源之前得先过两道关卡Authentication & Authorization

要想了解Identity中用户登录之后,后续的访问时怎样识别用户的,那首先我们得了解下认证(Authentication) 和授权(Authorization)的含义

游侠索罗:星球大战外传

主演:阿尔登·埃伦瑞奇 / 艾米莉亚·克拉克 / 唐纳德·格洛沃

猫眼电影演出 广告
购买

Authentication

Authentication就是认证的意思,还举之前公园的例子,我们拿到门票之后,去公园,入口门卫A首先要根据门票确认我们是谁?是老王,还是老赵,门票是不是真的,过期没。这个过程,这个识别来访者是谁的过程就叫做

Authentication(身份认证过程)

那Authorization 又是啥?

这两个单词太像了,甚至他们的释义都很像,以至于我们在不了解他们的时候总是弄混他们,Authorization是授权的意思,上一小节中,门卫A识别出了我们是谁?Ok,我们是老李,那么门卫B能不能让我们进园呢?不一定,门卫B还要再看,门票过期没,上一步已经看过门票是否过期了,为什么还要看呢?事情是这样的:门卫A看到门票过期了,然后在门票副卡上写上“门票过期”四个大字,再写上“认证失败”,但是负责认证的门卫A没有拦着我们,而是继续让我们前进,因为动物园可能因为活动而允许过期门票进入,或者没有门票也可以,那么接下来授权的人门卫B来看门票,他根据动物园切实的情况看,看看许可范围,再问问后台这个人是不是动物园的管理员。经过种种校验,发现,虽然门票过期了,但是今天是开放日,没门票也行,但是我们是普通游客,却来到了管理员通道,所以没让我们进园——授权失败

小结

好了,这就是认证和授权(Authentication & Authorization),两个不同的事,由两个不同的人(或者组件)来做

  • 认证用来确认来者是谁,确认身份(确认之后可能没有身份)

  • 授权用来确认持有此身份的来者能不能访问当前请求的资源

现在,我们要记住认证与授权中的一个要点

认证只确定用户是谁即使认证失败,也不会拦截用户访问,拦截用户访问发生在授权阶段

另外要注意的是 Authentication和Authorization并不属于Identity的一部分,都不属于Identity,它和Identity是相互独立的,然后一起协作。也就是说,即便我们没有使用Identity ,我们有我们自己的用户存储,角色等等和身份权限相关的一切,那么我们可以将我们的成员系统完美的与Asp.Net Core 进行集成,我们可以假设,Identity就是我们写的,然后将其与Asp.Net Core进行集成

那么为什么要将这个与Identity无关的认证过程Authentication放在这里呢?因为它们是协作的 Authentication和Authorization本事就是要与成员系统协作的,在代码上,他们解耦并且独立,但是在事实逻辑上,成员系统和认证授权总是一起使用的,所以一起讲容易理解

那么这篇文章只讲 Authentication与Authorization中的第一个 —— Authentication,先来了解一下,asp.net core 是怎样知道我们已经登陆的访客是谁的


身份认证中间件 Authentication Middleware

中间件(Middleware)讲起来又是一个长长的故事,如果你完全没概念,那么我建议你先简单学习一下asp.net core 中的中间件,你只要知道它的运行原理即可

在一般的asp.net core web 项目中,我们一般把身份认证中间件放在 静态文件中间件之后,Mvc中间件之前

public void Configure(IApplicationBuilder app, IHostingEnvironment env){    app.UseStaticFiles();    app.UseAuthentication();    app.UseMvc(routes =>    {        //略...    }); }


这样做的目的很简单,仅对需要认证的部分做认证

在http请求到达 mvc中间件之前,也就是进入我们写的逻辑代码之前,身份认证就结束了,也就是说,身份认证不能在 controller action中控制

我们用一张图来简化发生在身份认证中间件中的认证过程,注意,这里马上要引入一个新的概念

身份认证 handler

中间件是嵌在中间件管道中的一个一个模块,http请求有条件的流经他们

另一个相似的东西,有很多 handler 嵌在身份认证中间件上,那么http是流经所有的handler吗?

Authentication Handler

Authentication Hander 顾名思义,他就是切实处理身份认证的组件,它附加在 authentication middleware 上,在请求到来时, middleware 会在所有附加在它之上的handler中选取一个用来做身份认证

那么当我们使用Identity时,哪些 authentication handler 被附加了呢?当请求到来时,authentication middleware 如何知道要选择哪个handler呢?

接下来,我们一一解答

Cookie Authentication Handler

Identity只添加了一种类型的 handler ——CookieAuthenticationHandler

在我们的StartUp类中的ConfigureServices方法中,我们添加了Identity的Service

services.AddIdentity<ApplicationUser, IdentityRole>()    .AddEntityFrameworkStores<ApplicationDbContext>()    .AddDefaultTokenProviders();

但事情没这么简单,在添加Identity的同时,Identity还未我们的项目添加了AuthenticationService和CookieAuthenticationHandler


public static IdentityBuilder AddIdentity<TUser, TRole>( {   

 // Services used by identity    services.AddAuthentication(options =>    {        options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;        // 略...    })   

 .AddCookie(IdentityConstants.ApplicationScheme, o =>    {    // 略...    

在services.AddAuthentication的内部添加了AuthenticationService

namespace Microsoft.Extensions.DependencyInjection{  

 public static class AuthenticationCoreServiceCollectionExtensions    {        

public static IServiceCollection AddAuthenticationCore(this IServiceCollection services)  

     {            services.TryAddScoped<IAuthenticationService, AuthenticationService>();            services.TryAddScoped<IAuthenticationHandlerProvider, AuthenticationHandlerProvider>();            services.TryAddSingleton<IAuthenticationSchemeProvider, AuthenticationSchemeProvider>();

注意上面代码的最后三行,后面涉及到他们的获取,他们就是在此处添加的

namespace Microsoft.Extensions.DependencyInjection{  


 public static class CookieExtensions    {        


public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<CookieAuthenticationOptions> configureOptions)     

   {            builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());        

    return builder.AddScheme<CookieAuthenticationOptions, CookieAuthenticationHandler>(authenticationScheme, displayName, configureOptions);


上方的代码添加了 CookieAuthenticationHandler

在添加Authentication service的同时,制定默认的 authentication scheme(这个概念在之前的文章中提到过,如果你还有印象的话) 是谁(就是下方的cookie authentication handler)

这时候另一个问题浮现了,只添加了一个 cookie authentication handler,为什么还要将他制定成默认值,是否有有点多此一举呢?

虽然Identity只添加了一种类型的 handler(cookie authentication handler),但是他同时添加了多个

在 authentication 中间件上,区分各个handler的方法是指定不同的 authentication scheme,而不是通过 handler 的类型

其实它添加了这么多:

services.AddAuthentication(options =>

{

    options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;

    options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;

    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;

})

.AddCookie(IdentityConstants.ApplicationScheme, 略)

.AddCookie(IdentityConstants.ExternalScheme, 略)

.AddCookie(IdentityConstants.TwoFactorRememberMeScheme, 略)

.AddCookie(IdentityConstants.TwoFactorUserIdScheme,略);

不过我们暂时不用关心这些是什么

目前为止我们已经知道了这样几件事:

  1. 添加Identity时,Identity添加了用于身份认证的服务,以及默认激活的用于认证的handler——CookieAuthenticationHandler

  2. Identity的身份认证基于cookie (上篇文章我们了解到 Identity在登陆时将票据加密写入了cookie)

  3. 所以用户登录后再次访问的时候,会通过cookie来识别当前用户是谁

动手实践

这一小节中我们先编写测试代码,来看看认证过程产生了哪些结果

创建一个名为TestAuthController的控制器,代码大致如下:

namespace IdentityInAction.Controllers

{

    public class TestAuthController : Controller

    {

        public IActionResult Index()

        {

            return Json(new

            {

                User.Identity.IsAuthenticated,

                User.Identity.AuthenticationType,

                Claims=User.Claims.Select(c => new { c.Type, c.Value })

                // 略...

这些代码将返回一个json字符串,内容是 authentication的部分结果和用户的claims信息,这三行核心代码的意思分别是:

  • 用户是否已经通过身份认证

  • 对次请求进行认证的handler的名称(在上篇文章中我们有提到 authentication scheme 就是 authentication type的另一个名字,记住这件事对我们的理解很有帮助)

  • 这个用户的Claims信息

运行程序,不要进行登陆,如果已经登陆了则退出登陆,退出登陆的链接是右上角的LogOut

然后访问http://localhost:{你的端口}/testauth/index,得到的结果如下:

{  "isAuthenticated": false,  "authenticationType": null,  "claims": [] }

由于没有用户登陆,所以结果里几乎什么都没有,然后再尝试登陆后再次访问这个地址,结果如下:

{

  "isAuthenticated": true,

  "authenticationType": "Identity.Application",

  "claims": [

    {

      "type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",

      "value": "78a032c7-0d67-4cec-b031-2d15a7bac755"

    },

    {

      "type": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",

      "value": "abc@abc.com"

    },

    {

      "type": "AspNet.Identity.SecurityStamp",

      "value": "babbb46b-6ba0-4b87-875a-92088197dfbf"

    }

  ]

}


"isAuthenticated": true 这代表认证成功

"authenticationType": "Identity.Application"这是对该请求进行认证的handler的名字,由前文我们知道,我们默认的handler是名为IdentityConstants.ApplicationScheme的cookie handler,我们看一小段源代码证实一下:

public class IdentityConstants

{

    private static readonly string CookiePrefix = "Identity";

    public static readonly string ApplicationScheme = CookiePrefix + ".Application";

正如所料,接下来就是claims了,再上篇文章中提到再登陆过程中加入到Identity的claims有这些:

  • UserName | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier

  • UserId| http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name

  • SecurityStamp(如果支持的话)| AspNet.Identity.SecurityStamp

  • 存储在数据库中的额外Claims(如果支持的话)(注:支持,但当前用户没有)

这些claims随着票据一起加密写到了cookie中,现在他们又随着cookie一起传了回来
要注意的是,即便我们退出登陆后没有身份认证失败了,但是我们仍然获得了这个Uri的访问权限,原因在于认证并不阻止用户,授权才会阻止用户,而我们没又做授权方面的限制

看到这里,我们的认证过程的大体已经清楚了,接下来我们要看下整个认证过程的一点细节,整个过程是自上而下的,看标题为工作的那一列

工作注释
获取IAuthenticationHandlerProvider的实例
获取默认的AuthenticationScheme
使用上一步的scheme获取IAuthenticationService实例
上一步的service通过第一步的IAuthenticationHandlerProvider获取handlerhandler 是 cookie authentication  handler
handler 调用 AuthenticateAsync,这个方法最终调用了handler的HandleAuthenticateAsync①这个方法是事实上执行认证的方法
获取 CookieAuthenticationOptions.Cookie.Name指定的存储票据的cookie的原始字符串这个Name的默认值是`.AspNetCore.Identity.Application`
解密cookie字符串获得AuthenticationTicket的实例
检查是否使用了session存储,如果有则验证是否存在对应的session
检查cookie 是否过期
检查是否需要刷新cookie
创建新的AuthenticationTicket
将AuthenticationTicket中的Principal设置到HttpContext.User上,认证结束在动手做一节中,我们使用的User就是在这个时候被赋值的

需要注意

① 谁进行的验证

Identity的实现比较复杂,兜兜转转最终的验证时由 cookie authentication handler 的 HandleAuthenticateAsync完成的,如果你在看Identity源代码的话,那么直接跳转到这里可以节省时间

怎么验证的

事实上,说的简单一点,就是在登陆的时候,把票据加密写到cookie里,验证的时候

获取cookie >解密 >还原成票据 >把票据塞到http context中

即使是认证失败了,也是这4个步骤,最终 负责授权的组件会检查 http context 中的票据,还会结合其它情况来确定是否允许当前的请求继续进行下去,而我们的逻辑代码中也可以查看票据,根据不同的 认证结果 返回不同的数据

相关文章: 

  • ASP.NET Core Identity 实战(1)——Identity 初次体验

  • ASP.NET Core Identity Hands On(2)——注册、登录、Claim

  • 用 Identity Server 4 (JWKS 端点和 RS256 算法) 来保护 Python web api

  • 基于OIDC(OpenID Connect)的SSO

  • 学习Identity Server 4的预备知识

  • 使用Identity Server 4建立Authorization Server (1)

  • 使用Identity Server 4建立Authorization Server (2)

  • 使用Identity Server 4建立Authorization Server (3)

  • 使用Identity Server 4建立Authorization Server (4)

  • 使用Identity Server 4建立Authorization Server (5)

  • IdentityServer4(10)- 添加对外部认证的支持之QQ登录

  • spring cloud+.net core搭建微服务架构:Api授权认证(六)

原文地址: 

https://www.cnblogs.com/rocketRobin/p/9105720.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

RocketRobin

Reward

长按二维码向我转账

pic_reward_qrcode.2x3534de.png

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321236.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简明 ASP.NET Core 手册

编者&#xff1a;在4月份推送过这篇文章 简明 ASP.NET Core 手册 &#xff0c;今天再次推荐这篇文章&#xff0c;是因为原作者更新到了新版本1.1.0&#xff0c;改动很大&#xff0c;几乎所有章节都有很大程度的调整&#xff0c;这些调整都是根据读者的建议而做&#xff0c;而且…

《你必须掌握的Entity Framework 6.x与Core 2.0》正式出版感想

前言借书正式出版之际&#xff0c;完整回顾下从写博客到写书整个历程&#xff0c;也算是对自己近三年在技术上的一个总结&#xff0c;整个历程可通过三个万万没想到来概括&#xff0c;请耐心阅读。写博、写书完整历程回顾从2013年12月注册博客园账号&#xff0c;注册博客园账号…

Entity Framework Core 2.1带来更好的SQL语句生成方案

微软发布了Entity Framework Core2.1&#xff0c;为EF开发者带来了很多期待已久的特性。EF Core 2.1增加了对SQL GROUP BY的支持&#xff0c;支持延迟加载和数据种子等。EF Core 2.1的第一个重要新增特性是将GroupBy操作符翻译成包含GROUP BY子句的SQL。缺乏这种支持被认为是EF…

【枚举】数列(jzoj 1507)

数列 题目大意&#xff1a;给出一个等差数列的初始值和差值还有一个等比数列的处值和比值&#xff0c;问不大于n的数中&#xff0c;问这两个序列中&#xff0c;有多少个数小于n&#xff08;只要在一个序列中就行了&#xff0c;在两个序列中只记一次&#xff09; 样例输入 1 …

【模拟】蚂蚁(jzoj 1508)

蚂蚁 题目大意&#xff1a; 有n只蚂蚁&#xff0c;他们各往一个方向走&#xff08;上北&#xff0c;下南&#xff0c;左西和有东四个方向&#xff09;&#xff0c;他们如果撞到一起就会直接消失&#xff0c;每个单位时间走一格&#xff0c;但有一种情况&#xff1a;两只蚂蚁相…

【结论】单元格(jzoj 1509)

单元格 题目大意&#xff1a; 在一个RC的矩形中选三个点&#xff0c;使他们行列各不同&#xff0c;定义“费用”为&#xff0c;这三个点之间的行列的差值的和&#xff08;1,2和3,4费用是差值是&#xff08;3-1&#xff09;&#xff08;4-2&#xff09;224&#xff09;&#x…

【DP】剪草(jzoj 1510)

剪草 题目大意&#xff1a; 有n棵小草&#xff0c;B某看它们很不顺眼&#xff0c;想让他们的高度总和不大于H&#xff0c;它们一开始各有一个高度&#xff0c;然后它们各有一个固定的生长值&#xff0c;B某每个单位时间可以将一棵草减掉&#xff08;让他的高度变为0&#xff…

codeforces 962E Byteland, Berland and Disputed Cities 最小生成树变形

题目 题目链接 题意 在OxOx轴上有一堆点&#xff0c;这些点有三种类型R、B、PR、B、P型&#xff0c;现在要求添加一些线段把这些点连起来&#xff0c;使得如果去掉RR类型点,剩下的点都是联通的。如果去掉B" role="presentation" style="position: rela…

P6772-[NOI2020]美食家【矩阵乘法,倍增】

前言 我考场&#xff08;线上赛&#xff09;切NOI的题了&#xff01; 正题 题目链接:https://www.luogu.com.cn/problem/P6772 题目大意 nnn个点mmm条边&#xff0c;每个城市有不同的愉悦值&#xff0c;从111出发&#xff0c;要求经过TTT的时间后回到点111(不能原地停留。 …

在ASP.NET Core中使用brotli压缩

Brotli是一种全新的数据格式&#xff0c;可以提供比Zopfli高20-26%的压缩比。据谷歌研究&#xff0c;Brotli压缩速度同zlib的Deflate实现大致相同&#xff0c;而在Canterbury语料库上的压缩密度比LZMA和bzip2略大。 链接&#xff1a;Google开源Brotli压缩算法 微软使用了一种基…

CUMT--Java复习--文件及IO流

目录 一、文件 1、文件系统和路径 2、File类 3、FilenameFilter接口 二、IO流 1、流的分类 2、流的体系结构 三、字节流 1、InputStream 2、OutputStream 四、字符流 1、Reader 2、Writer 五、过滤流和转换流 1、过滤流 2、转换流 六、序列化 1、对象序列化…

用ASP.NET Core 2.1 建立规范的 REST API -- 翻页/排序/过滤等

本文所需的一些预备知识可以看这里: 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 和 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 (2) 准备项目建立Richardson成熟度2级的POST、GET、PUT、PATCH、DELETE的RESTful API请看这里&#xff1a; 用ASP.NET Core…

用ASP.NET Core 2.1 建立规范的 REST API -- HATEOAS

本文所需的一些预备知识可以看这里: 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 和 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 (2) 准备项目建立Richardson成熟度2级的POST、GET、PUT、PATCH、DELETE的RESTful API请看这里&#xff1a;用ASP.NET Core …

学习手记(2020/8/19~2021/3/19)

文章目录所有集合子集数量和结论证明枚举子集的方法最大匹配模的次数线性基卡特兰数树形dpTipTipTip斯特林数斐波那契幂前缀和hallhallhall定理阿巴阿巴1狄利克雷卷积常用式子组合数学恒等式竞赛图性质一些博弈模型基础反演二项式反演莫比乌斯反演欧拉反演子集反演min-max\text…

奶牛的交叉路(jzoj 1756)

奶牛的交叉路 题目大意&#xff1a; 有两个数轴&#xff0c;之间有n条线分别连接着两个数轴的点各一个&#xff0c;这些线可能会相交&#xff0c;问有多少条线没有和其他点相交 样例输入 4 -3 4 7 8 10 16 3 9样例输出 2数据范围限制 1<N<100000&#xff0c;-1…

.Net Core 环境下构建强大且易用的规则引擎

1. 引言1.1 为什么需要规则引擎在业务的早期时代&#xff0c;也许使用硬编码或者逻辑判断就可以满足要求。但随着业务的发展&#xff0c;越来越多的问题会暴露出来&#xff1a;逻辑复杂度带来的编码挑战&#xff0c;需求变更时改变逻辑可能会引起灾难重复性的需求必须可重用&am…

【最短路】【SPFA】单源最短路径 (luogu 3371)

单源最短路径 luogu 3371 题目大意&#xff1a; 求出一个点到其他点的最短路 原题&#xff1a; 题目背景 本题测试数据为随机数据&#xff0c;在考试中可能会出现构造数据让SPFA不通过&#xff0c;如有需要请移步 P4779。 题目描述 如题&#xff0c;给出一个有向图&…

在Windows 下如何使用 AspNetCore Api 和 consul

一、概念&#xff1a;什么是consul:Consul 是有多个组件组成的一个整体&#xff0c;作用和Eureka,Zookeeper相当&#xff0c;都是用来做服务的发现与治理。 Consul的特性&#xff1a;1、 服务的发现&#xff1a;consul可以把注册到其中的服务提供给使用者&#xff0c;也可以主动…

网络流及建模专题(下)

前言 不断更新中… 专题的(下)篇将介绍网络流的一些奇奇怪怪的应用和费用流有关的一些套路。 本专题暂时包含三道题&#xff1a; 洛谷P1251 餐巾计划问题: 费用流的基本应用 Trade Gym - 100212I: 使用网络流对图论中的边进行调整 codeforces 818G - Four Melodies: 费用…

CentOS 7.4 下 如何部署 AspNetCore 结合 consul

上篇我们讲到consul的概念&#xff0c;以及在WIN下如何使用&#xff1a; 在Windows 下如何使用 AspNetCore Api 和 consul步骤如下&#xff1a;1、安装虚拟机VM 2、下载安装 CentOS 7.4&#xff08;地址就不提供了&#xff09;这是安装示例&#xff1a; VM虚拟机安装CentOS 示例…