前言

在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(ASP.NET Core 之 Identity 入门(一),ASP.NET Core 之 Identity 入门(二),ASP.NET Core 之 Identity 入门(三)奠定一下基础。

有关于 Authentication 的知识太广,所以本篇介绍几个在 ASP.NET Core 认证中会使用到的中间件,还有Authentication的一些零碎知识点,这些知识点对于 ASP.NET 认证体系的理解至关重要。

在 Github 中 ASP.NET Core 关于 Authentication 的实现有以下几个包,那么这几个包的功能分别是干什么用的呢?我们一一看一下。

  • Microsoft.AspNetCore.Authentication

  • Microsoft.AspNetCore.Authentication.Cookies

  • Microsoft.AspNetCore.Authentication.OAuth

  • Microsoft.AspNetCore.Authentication.OpenIdConnect

  • Microsoft.AspNetCore.Authentication.JwtBearer

Microsoft.AspNetCore.Authentication

Authentication 在 ASP.NET Core 中,对于 Authentication(认证) 的抽象实现,此中间件用来处理或者提供管道中的 HttpContext 里面的 AuthenticationManager 相关功能抽象实现。

HttpContext 中的 User 相关信息同样在此中间件中被初始化。

对于开发人员只需要了解此中间件中的这几个对象即可:

  • AuthenticationOptions 对象主要是用来提供认证相关中间件配置项,后面的 OpenIdConnect,OAuth,Cookie 等均是继承于此。

  • AuthenticationHandler 对请求流程中(Pre-Request)中相关认证部分提供的一个抽象处理类,同样后面的其他几个中间件均是继承于此。

在 AuthenticationHandler 中, 有几个比较重要的方法:

  • HandleAuthenticateAsync :处理认证流程中的一个核心方法,这个方法返回 AuthenticateResult来标记是否认证成功以及返回认证过后的票据(AuthenticationTicket)。

  • HandleUnauthorizedAsync:可以重写此方法用来处理相应401未授权等问题,修改头,或者跳转等。

  • HandleSignInAsync:对齐 HttpContext AuthenticationManager 中的 SignInAsync

  • HandleSignOutAsync:对齐 HttpContext AuthenticationManager 中的 SignOutAsync

  • HandleForbiddenAsync:对齐 HttpContext AuthenticationManager 中的 ForbidAsync,用来处理禁用等结果

以上关于 AuthenticationHandler 我列出来的这些方法都是非常容易理解的,我们在继承Authentication实现我们自己的一个中间件的时候只需要重写上面的一个或者多个方法即可。

还有一个 RemoteAuthenticationHandler 它也是继承AuthenticationHandler,主要是针对于远程调用提供出来的一个抽象,什么意思呢?因为很多时候我们的认证是基于OAuth的,也就是说用户的状态信息是存储到Http Header 里面每次进行往来的,而不是cookie等,所以在这个类里面了一个HandleRemoteAuthenticateAsync的函数。

Microsoft.AspNetCore.Authentication.Cookies

Cookies 认证是 ASP.NET Core Identity 默认使用的身份认证方式,那么这个中间件主要是干什么的呢

我们知道,在 ASP.NET Core 中已经没有了 Forms 认证,取而代之的是一个叫 “个人用户账户” 的一个东西,如下图,你在新建一个ASP.ENT Core Web 应用程序的时候就会发现它,它实际上就是 Identity。那么Forms认证去哪里了呢?对,就是换了个名字叫 Identity。

在此中间件中,主要是针对于Forms认证的一个实现,也就是说它通过Cookie把用户的个人身份信息通过加密的票据存储的Cookie中去,如果看过我之前Identity系列文章的话,那么应该知道用户的个人身份信息就是 ClaimsIdentity 相关的东西。

这个中间件引用了Authentication,CookieAuthenticationHandler 类继承了 AuthenticationHandler 并重写了 HandleAuthenticateAsync,HandleSignInAsync,HandleSignOutAsyncHandleForbiddenAsync,HandleUnauthorizedAsync 等方法,就是上一节中列出来的几个方法。

我们主要看一下核心方法 HandleAuthenticateAsync 在 Cookie 中间件怎么实现的:

protected override async Task<AuthenticateResult> HandleAuthenticateAsync(){    //读取并解密从浏览器获取的Cookievar result = await EnsureCookieTicket();    if (!result.Succeeded){        return result;}     // 使用上一步结果构造 CookieValidatePrincipalContext 对象// 这个对象是一个包装类,里面装着 ClaimsPrincipal、AuthenticationPropertiesvar context = new CookieValidatePrincipalContext(Context, result.Ticket, Options);    // 默认是空的实现,可以重写来验证 CookieValidatePrincipalContext 是否有异常await Options.Events.ValidatePrincipal(context);    if (context.Principal == null){        return AuthenticateResult.Fail("No principal.");}    // 表示是否需要刷新Cookieif (context.ShouldRenew){RequestRefresh(result.Ticket);}    return AuthenticateResult.Success(new AuthenticationTicket(context.Principal, context.Properties, Options.AuthenticationScheme));
}

总结一下就是解密Http请求中的Cookie信息,然后验证Cookie是否合法,然后提取Cookie中的信息返回结果。

还有一个方法就是 HandleSignInAsync ,根据名字可以看出主要是处理登入相关操作的,在这个方法里面主要是根据Claims信息生成加入过后的票据,同时会向票据中写入过期时间,是否持久化等信息。 是否持久化的意思就是用户在登陆界面是否勾选了 “记住我” 这个操作。

Microsoft.AspNetCore.Authentication.OAuth

OAuth 是针对于 OAuth 2.0 标准实现的一个客户端程序,记住是客户端,它不具备发放Token或者 Client_id ,Code 等的功能,它的作用是帮你简化对OAuth2.0服务端程序的调用。 它对应 OAuth 2.0 标准中的 “获取Access_Token” 这一步骤,如果对腾讯开放平台QQ授权比较了解的话,就是对应 “使用Authorization_Code获取Access_Token” 这一步骤。

点击 这里 查看图片详情。

OAuth 实现的具体细节就不一一介绍了。

Microsoft.AspNetCore.Authentication.OpenIdConnect

获取 OpenId 是OAuth 授权中的一个步骤,OpenId 它是具体的一个Token Key,不要把他理解成一种授权方式或者和OAuth不同的另外一种东西,他们是一体的。

代码上就不详细说了,和上面的都差不多。主要说一下它们之间的区别或者叫联系。

OAuth 它主要是针对于授权(Authorization),而OpenID主要是针对于认证(Authentication),他们之间是互补的。

那什么叫授权呢? 比如小明是使用我们网站的一个用户,他现在要在另外一个网站使用在我们网站注册的账号,那授权就是代表小明在另外一个网站能够做什么东西? 比如能够查看资料,头像,相册等等,授权会给用户发放一个叫 Access_Token 的东西。

而认证关注的这个用户是谁,它是用来证明用户东西。比如小明要访问它的相册,那我们网站就需要小明提供一个叫OpenId的一个东西,我们只认这个OpenId。那小明从哪里得到它的这个OpenId呢,对,就是使用上一步的Access_Token 来换取这 个 OpenId ,以后访问的时候不认 Access_Token ,只认识OpenId这个东西。

一般情况下,OpenId 是需要客户端进行持久化的,那么对应在 ASP.NET Core Identity 中,就是存储在 UsersLogin 表里面的 ProviderKey 字段,懂了吧,懂了给个推荐呗

Microsoft.AspNetCore.Authentication.JwtBearer

JwtBearer 这个中间件是依赖于上一步的 OpenIdConnect 中间件的,看到了吧,其实这几个中间件是环环嵌套的。

可能很多同学听说过 Jwt,但是大多数人都有一个误区,认为JWT是一种认证方式,经常在QQ群里面听过 前面一个同学在问 实际开发中前后端分离的时候安全怎么做的?,下面一个人回答使用JWT。

其实JWT 它不是一种认证方式,也不是一种认证的技术,它是一个规范,一个标准。

Jwt(Json Web Token)的官网是 https://jwt.io,下面是对JWT的一个说明

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
JSON Web Tokens(JWT) 是一个开放的行业标准( RFC 7519),用于在双方之间传递安全的Claims。

JWT 在身份认证中的应用场景:

在身份认证场景下,一旦用户完成了登陆,在接下来的每个请求中包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录(SSO)中比较广泛的使用了该技术。

好了,不过多的说了。 我们还是接着看一下 JwtBearer 中间件,同样它重写了 HandleAuthenticateAsync 方法。

大致步骤如下:

  1. 读取 Http Request Header 中的 Authorization 信息

  2. 读取 Authorization 值里面的 Bearer 信息

  3. 验证 Bearer 是否合法,会得到一个 ClaimsPrincipal

  4. 使用 ClaimsPrincipal 构建一个 Ticket(票据)

  5. 调用 Options.Events.TokenValidated(context),用户可以重写此方法验证Token合法性

  6. 返回验证成功

其他的知识点

这几个中间件对会有对应的 Options 配置项,在这些配置项中,都会有 AuthenticationSchemeAutomaticAuthenticateAutomaticChallenge 这几个属性,那这几个东西都是干嘛的呢?

AuthenticationScheme

我在 《ASP.NET Core 之 Identity 入门(二)》 一文中提到过这个知识点,当时说很重要,这里可以看到了吧,每一种验证中间件都会使用到这个东西,我比较偏向于把这个翻译成 “认证方案”。

我们知道,在 MVC 程序中一般通过在 Controller 或者 Action 上 打标记(Attribute)的方式进行授权,最典型的就是新建一个项目的时候里面的AccountController。

[Authorize]public class AccountController : Controller{
}

在 Authorize 这个 Attribute 中,有一个属性叫做 ActiveAuthenticationSchemes 的东西,那么这个东西是干什么用的呢?

ActiveAuthenticationSchemes 就是对应着中间件Options里面配置的 AuthenticationScheme ,如果你不指定的话,在使用多个身份验证组件的时候会有问题,会有什么问题呢?往下看

AutomaticAuthenticate

AutomaticAuthenticate 很简单,是一个bool类型的字段,用来配置是否处理 AuthenticationHandler 是否处理请求。或者你可以理解为中间件是不是自动的处理认证相关的业务。

AutomaticChallenge

这个重要哦! 当我们使用多个身份验证中间件的时候,那么就要用到这个配置项了,该配置项是用来设置哪个中间件会是身份验证流程中的默认中间件,当代码运行到 Controller 或者 Action 上的 [Authorize] 这个标记的时候,就会触发身份验证流程。默认情况下MVC的Filter会自动的触发[Authorize],当然也有一种手动触发Authorize的办法就是使用HttpContext.Authentication.ChallengeAsync()

实际上,在验证中间件的管道流程中,应该只有一个组件被设定为 AutomaticChallenge = true,但其实大多数的中间件这个参数默认都是 true ,这些中间件包括(Identity, Cookie, OAuth, OpenId, IISIntegration, WebListener)等, 这就导致了在整个验证流程中会触发多个中间件对其进行相应,这种冲突大部分不是用户期望的结果。

不幸的是,目前框架对于这种情况并没有一个健壮的机制,如果开发人员对于这种机制不是很清楚的话,可能会造成很大的困扰。

幸运的是,ASP.NET Core 团队已经意识到了这个问题,他们将在 NET Standard 2.0 中对此重新进行设计,比如手动触发的时候应该怎么处理,有多个的时候怎么处理,以及会添加一些语法糖。

目前情况下,当有多个验证中间件的时候,应该怎么处理呢?比如同时使用 Identity 和 JwtBearer。正确的做法是应该禁用掉除 Identity 以外的其他中间件的 AutomaticChallenge,然后指定调用的AuthenticationScheme。也就是说在Controller或者Action显式指定 [Authorize(ActiveAuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] ,或者是可以指定一个策略来简化授权调用 [Authorize("ApiPolicy")]

services.AddAuthorization(options =>
{options.AddPolicy("ApiPolicy", policy =>{policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);policy.RequireAuthenticatedUser();});
});

而默认不带参数的 [Authorize] 可以指定AuthorizationPolicie:

services.AddAuthorization(options =>
{options.DefaultPolicy = new AuthorizationPolicyBuilder("Identity.Application").RequireAuthenticatedUser().Build();
});

注意,手动调用 HttpContext.Authentication.ChallengeAsync() 不受 AuthorizationPolicie 影响。

总结

本篇介绍了 ASP.NET Core 有关 Authentication 的几个中间件,然后还有几个比较重要的知识点,这篇文章内容有点多,对于一些人来说可能需要一点时间消化。

相关文章:

原文地址:http://www.cnblogs.com/savorboard/p/aspnetcore-authentication.html

.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

ASP.NET Core 中的那些认证中间件及一些重要知识点相关推荐

  1. asp向不同的用户发送信息_ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

  2. 如何简单的在 ASP.NET Core 中集成 JWT 认证?

    前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...

  3. 如何在 ASP.NET Core 中使用 URL Rewriting 中间件

    URL rewriting 是根据预先配置好的一组规则去修改 request url,值得注意的是:URL Rewriting 的重写功能和 url 重定向 是两个概念,本篇我们就来讨论下如何在 AS ...

  4. 在ASP.NET Core中编写合格的中间件

    这篇文章探讨了让不同的请求去使用不同的中间件,那么我们应该如何配置ASP.NET Core中间件?其实中间件只是在ASP.NET Core中处理Web请求的管道.所有ASP.NET Core应用程序至 ...

  5. ASP.NET Core中HTTP管道和中间件的二三事

    本文出自<从零开始学ASP.NET CORE MVC> 推荐文章:中间件是什么?在.NET Core中的工作原理又是怎样的呢? 配置ASP.NET Core请求(Request)处理管道 ...

  6. ASP.NET Core 中基于工厂的中间件激活

    IMiddlewareFactory/IMiddleware 是中间件激活的扩展点. UseMiddleware 扩展方法检查中间件的已注册类型是否实现 IMiddleware. 如果是,则使用在容器 ...

  7. 理解ASP.NET Core中的中间件

    中间件是ASP.NET Core的一个重要特点,ASP.NET Core应用程序之所以能够灵活地处理各种各样的请求,完成都是由于中间件,那么它究竟是怎么一回事呢? 一.理解中间件 ASP.NET Co ...

  8. 如何在 ASP.NET Core 中 自定义中间件

    ASP.NET Core 是一个跨平台,开源的,轻量级,高性能 并且高度模块化的web框架,同时扩展性也是非常强,你可以在 request -> response 请求管道中安插各种中间件来根据 ...

  9. 如何在 ASP.Net Core 中使用 条件中间件

    ASP.Net Core 是微软开源的跨平台.可扩展.轻量级的模块化框架,可用于构建高性能的web应用程序.中间件组件可以注入到 ASP.Net Core 请求管道中实现对 Request 和 Res ...

最新文章

  1. jQuery绑定事件的三种常见方式(bind、one、【change、click、keydown、hover】)
  2. 计算机导论第一章试题及答案,计算机导论第一章试题
  3. linux启动lsyncd服务,Ubuntu下lsyncd实现远端实时同步配置
  4. 深度学习导论(3)PyTorch基础
  5. Linux文件查看/编辑方法介绍
  6. 【Python】python3编码方式encode介绍
  7. python小型登录系统_python实现用户登录系统
  8. python爬取小视频-今天给大家带来了python抓取b站小视频的小爬虫
  9. matlab学习笔记杂项一
  10. 八.nginx网站服务实践应用
  11. Producer-Consumer question : OO 生产者-消费者:面向对象
  12. 编曲软件FL Studio 20.99中文版2023最新免费下载
  13. Windows server 下关闭135/139/445端口
  14. VMware虚拟文件(.vmdk)瘦身(宿主为Windows)
  15. 树梅派 raspberrypi 更换清华源
  16. 自己搭建服务器提供IOS IPA包下载
  17. cache tier 分级缓存
  18. MySQL教程——4 高级篇(性能调优、锁)
  19. TM1637数码管显示 HAL库
  20. ps流 转发_一种国标PS流转RTMP直播流的实时转换方法与流程

热门文章

  1. AgileConfig 1.6.0 发布 - 支持服务注册与发现
  2. .NET 编码的基础知识
  3. 2021.NET大会日程首发!行程亮点全曝光!
  4. Envoy实现.NET架构的网关(一)静态配置与文件动态配置
  5. 《Redis核心技术与实战》学习总结(2)
  6. .NET 6 新特性 System.Text.Json 中的 Writeable DOM
  7. 面向.NET开发人员的Dapr——机密
  8. IComparer实现文件名排序
  9. C# 9 新特性——init only setter
  10. 多线程并发如何高效实现生产者/消费者?