asp.net core 3.x 身份验证-1涉及到的概念

前言

从本篇开始将围绕asp.net core身份验证写个小系列,但愿你看完本系列后,脑子里对asp.net core的身份验证原理有个大体印象。
至于身份验证是啥?与受权有啥联系?就不介绍了,太啰嗦。你若是不晓得,本身去搜搜吧。
个人学习思路是详细看源码 > 总结得出一个宏观上的印象 + 如何使用。
若是发现有啥讲错的望指正,省得误导观众git

咱们偶尔会思考如何设计一个牛X的软件,其实经过对asp.net core框架自己的学习更划算,一来咱们熟悉了asp.net core框架,再者咱们学习了微软碰到需求是如何设计的。github

计划:数据库

  • 基本介绍 - 概述 + 核心类介绍
  • 基于cookie/session的身份验证原理 - 适合浏览器
  • 基于Token身份验证 - 适合移动端app
  • 集成第三方登陆原理 - 好比集成微信、支付宝登陆
  • IdentityServer - 目前不鸟解
  • asp.net core Identity - 目前不鸟解

必备知识:asp.net core、配置、选项、依赖注入、中间件等...浏览器

参考:源码Artechmvc5基于owin的身份验证视频缓存

注意:本篇只讲涉及到的几个概念微信

 

身份验证方式和简易流程

常见的身份验证方式:cookie

  • 基于cookie/session的身份验证原理 - 适合浏览器
  • 基于Token身份验证 - 适合移动端app
  • 集成第三方登陆原理 - 好比集成微信、支付宝登陆

为了便于理解后续的概念,下面先以最多见的 用户密码+cookie的身份验证方式说说核心流程session

登陆:mvc

  1. 用户输入帐号密码提交
  2. 服务端验证帐号密码
  3. 若验证成功,则建立一个包含用户标识的票证(下面会说)
  4. 将票证加密成字符串写入cookie

携带cookie请求:app

  1. 用户发起请求
  2. 身份验证中间件尝试获取并解密cookie,进而获得含用户标识的票证(下面会说)
  3. 将用户标识设置到HttpContext.User属性

注意:若身份验证中间件即便没有解析获得用户标识,请求也会继续执行,此时以匿名用户的身份在访问系统

 

用户标识ClaimsPrincipal

它用来表示当前登陆的用户,它包含用户Id + 一些与权限检查相关的附件属性(角色、所属部门)
当请求抵达时“身份验证中间件”将从请求中解析获得当前用户,若是获取成功则赋值给HttpContext.User属性

因此对于咱们来讲一般有两个场景使用它
在任意能访问HttpContext的地方获取当前用户,好比在Controller中。
若是须要自定义实现身份验证,则咱们要千方百计从请求中解析获得用户,并赋值给HttpContext.User

如今你至少对用户标识这个概念有点理解了,若是要刨根问底儿就自行搜索关键字:asp.net Claims

也许你曾经作过或见过这样的设计,定义Employee表示当前系统的用户,当用户登陆时会从数据库查询获得对应的Employee,若帐号密码验证经过则将其放入Session或缓存中。下次访问时直接从Session/缓存中获取当前用户。我的以为这种设计存在以下问题:

  • 浪费内存:咱们的业务代码访问当前用户最多的字段可能只是用户id,性别、地址、联系电话、学历....这些字段不是每一个业务处理都须要的
  • 抛弃了asp.net身份验证框架:从asp.net 2.0时代微软就设计了IPrincipal,后续的版本直到mvc5中基于owin的身份验证都在使用此接口,后续的权限验证微软也提供了,也是基于此接口的,但咱们放弃了,反而是本身有写了一套微软自己就实现的功能,可能多数是以为本身写的更简单。但我以为判断哪一种方式更合适是在你对两种方式都了解的状况下再作出判断。

 

用户票证AuthenticationTicket

既然有了上面的用户标识,何不直接在登陆时加密这个标识,解析时直接解密获得呢?由于咱们还须要额外的控制,好比过时时间,这个属性只是在身份验证阶段来判断是否过时,在咱们(如Controller.Action中)使用用户标识的时候并不须要此字段,相似的额外字段根据不一样的身份验证方式可能有不少,所以定义了“用户票证”这个概念,它包含 用户标识 + 身份验证过程当中须要的额外属性(如获得用户标识的时间、过时时间等)

 

身份验证处理器AuthenticationHandler

参考上面的用户名密码+cookie身份验证流程咱们发现有几个核心的处理步骤:

  • 在登陆时验证经过后将用户标识加密后存储到cookie,SignIn
  • 当用户注销时,须要清楚表明用户标识的cookie,SignOut
  • 在登陆时从请求中获取用户标识,Authenticate
  • 在用户未登陆访问受保护的资源时,咱们但愿跳转到到登陆页,Challenge
    • Challenge叫作质询/挑战,意思是当发现没有从当前请求中发现用户标识是但愿怎么办,多是跳转到登陆页,也多是直接响应401,或者跳转到第三方(如QQ、微信)的登陆页 
  • 由于某种缘由(如权限验证不过),阻止方案,Forbid

身份验证处理器就是用来定义这些步骤的
asp.net core中定义了对应的接口、和抽象类,不一样的身份验证方式有不的实现类,好比基于token的身份验证方式在SignIn时直接加密票证而后返回这个字符串(而不是写入cookie)
这些步骤都是围绕身份验证来定义的,在不一样地方来调用(好比在登陆页对于的Action、在请求抵达时、在受权中间件中)

 

身份验证选项AuthenticationSchemeOptions

在上述身份验证处理的多个步骤中会用到一些选项数据,好比基于cookie的身份验证 cookeName、有效时长、再好比从请求时从cookie中解析获得用户标识后回调选项中的某个回调函数,容许咱们的代码向调试中添加额外数据,或者干脆替换整个标识。

因此身份验证选项用来容许咱们控制AuthenticationHandler的执行。不一样的身份验证方式有不一样的选项对象,它们直接或间接实现AuthenticationSchemeOptions

 

身份验证方案AuthenticationScheme

总结性的说:身份验证方案 = 名称 + 身份验证处理器类型,暂时能够理解一种身份验证方式 对应 一个身份验证方案,好比:
基于用户名密码+cookie的身份验证方式 对应的 身份验证方案为:new AuthenticationScheme("UIDPWDCookie",typeof(CookieAuthenticationHandler))
基于用户名密码+token  的身份验证方式 对应的 身份验证方案为:new AuthenticationScheme("JwtBearer",typeof(JwtBearerHandler))

身份验证方案在程序启动阶段配置,启动后造成一个身份验证方案列表。
程序运行阶段从这个列表中取出制定方案,获得对应的处理器类型,而后建立它,最后调用这个处理器作相应处理
好比登陆操做的Action中xxx.SignIn("方案名") > 经过方案名找到方案从而获得对应的处理器类型 > 建立处理器 > 调用其SignIn方法

一种特殊的状况可能多种方案使用同一个身份验证处理器类型,这个后续的集成第三方登陆来讲

 

身份验证方案的容器AuthenticationSchemeProvider

咱们说一个系统可能同时支持多种身份验证方案,所以咱们须要一个容器,能够把它理解为Dictionary<方案名,身份验证方案>

 

身份验证处理器容器AuthenticationHandlerProvider

能够暂时把它理解为Dictionary<方案名, 身份验证处理器容器>,由于这个对象是每次请求都会建立,而且它提供AuthenticationHandler时时从方案列表中去找到制定方案从而获得对应的处理器类型而后建立的。若是不理解不要紧,下一篇讲流程就懂了

 

身份验证服务AuthenticationService

身份验证中的步骤是在多个地方被调用的,身份验证中间件、受权中间件、登陆的Action(如:AccountController.SignIn())、注销的Action(如:AccountController.SignOut()),身份验证的核心方法定义在这个类中,但它本质上仍是去找到对应的身份验证处理器并调用其同名方法。其实这些方法还进一步以扩展方法的形式定义到HttpContext上了。以SignIn方法为例
HttpContext.SignIn() > AuthenticationService.SignIn() > AuthenticationHandler.SignIn() 

 

后续

这一篇只尽可能简单的说了下身份验证涉及到的几个核心概念,若是不明白的能够留言或等到下篇结合理解。下一篇将以用户名密码+cookie的身份验证方式来详细梳理下流程。

相关文章
相关标签/搜索