.NET Core中的认证管理解析
.NET Core中的认证管理解析
0x00 问题来源
在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册、登录等很多页面,也可以使用AuthorizeAttribute进行各种权限管理,看起来似乎十分方便。不过生成的代码都替我干了些什么我一团雾水。看了下生成的数据表,功能也挺复杂的。实际上我需要的只是基于用户和角色的认证管理,而且用户资料是使用现有的库,但使用.NET Core自带的认证组件必须要依赖EF,表的结构也很多对不上,所以学习了下自带的认证组件的实现,然后自己写了个认证服务替换了Identity组件,同时Cookie管理使用自带的Cookie中间件、可以使用AuthorizeAttribute进行认证。复杂的需求还没遇到,所以就学习到了这里。这篇博客主要讨论最简单情况下的的基于用户和角色的认证。关于.NET Core自带认证组件的一些基本用法,可以参考https://docs.asp.net/en/latest/security/authentication/accconfirm.html。
0x01 .NET Core中的认证管理
提到认证管理,首相想到的就是用户的注册、登录、注销以及给用户添加/删除角色等功能。其中用户信息,角色信息等都是保存在数据库中的。所以主要包含数据库操作和登录业务逻辑两部分。在登录业务逻辑层面,.NET Core主要通过三个比较核心的类UserManager、RoleManager、SigninManager进行管理(在Microsoft.AspNetCore.Identity程序集)。其中:
- UserManager主要负责用户的认证、注册、修改、删除以及与用户相关的角色、令牌、声明等的管理。
- RoleManager负责角色、角色相关声明的管理。
- SigninManager负责登录、注销等相关操作。在涉及到用户操作(如登陆时用户验证)会调用UserManager进行操作。
这三个核心类在操作数据库时,使用数据库层面的UserStore、RoleStore进行操作(在Microsoft.AspNetCore.Identity.EntityFrameworkCore程序集)。业务关系如下图所示:
我们在开发认证相关功能时使用这三个核心类即可满足大多数需求。我们在使用这几个核心类的对象时都是通过依赖注入获取的,那么这些相关的依赖是什么时候注入的呢?在Startup的ConfigureServices方法中有AddIdentity扩展方法,就是在这个方法中添加了需要的所有依赖。
0x02 登录和注销
了解了Identity组件的整体分工后,再来看一下登录和注销的操作的部分细节。登录和注销过程主要由SigninManager负责,的先来看一下登录的过程:
登录成功后Response的Header中包含了Set-Cookie,Cookie的Key需要和Cookie中间件中设置的要解密的Cookie的Key一致,在截图中这个Cookie的Key是IdentityCookie。设置Cookie的同时返回302重定向到登录页面。
重定向到登陆页面时,请求中已经带有设置的Key为IdentityCookie的Cookie了。
注销过程比较简单,调用HttpContext.Authentication.SignOutAsync方法即可注销,此时会给HttpContext.Response添加Set-Cookie,但内容为空。
0x03 通过Cookie识别用户
.NET Core中通过CookieAuthenticationMiddleware这个中间件识别HttpContext中认证相关的Cookie,从而添加用户的验证和授权信息。最关键的是ClaimsPrincipal对象,它记录用户的认证和授权信息(除此之外当然也可以包含其它你需求的任意信息),从上面登录过程可以看到,登录成功后用户认证和授权信息保存至ClaimsPrincipal对象(实际上对于这条Cookie键值对中的认证信息保存为ClaimsIdentity,一个ClaimsPrincipal可以包含多个ClaimsIdentity),然后在HttpContext.Response的Headers中添加Set-Cookie,Key为Cookie中间件中指定的CookieName,Value就是这个对象加密后的字符串。以后的HttpContext都会带有这个Cookie,Cookie中间件会把符合这个CookieName的Cookie取出来,解密并还原为ClaimsPrincipal对象,并把HttpContext.User设置为这个对象。后面MVC中间件在路由到相应Controller和Action的时候就可以根据Authorize特性中指定的认证和角色在HttpContext.User中进行检查,不满足检查则跳转至相应页面。因此需要注意的就是一定要把Cookie中间件放在MVC中间件之前。
这里需要特别说一下ClaimsPrincipal。一个ClaimsPrincipal对象中包含了一个或多个ClaimsIdentity对象,一个ClaimsIdentity对象一般来说对应着一个Cookie中某条键值对(个人理解)。Cookie中间件和ClaimsIdentity是通过AuthenticationScheme联系起来的。后面我们在写自己的认证服务时,也是把Cookie中间件的AuthenticationScheme和创建的ClaimsIdentity一致。所以更准确地说是ClaimsIdentity包含了用户认证和权限的声明,而ClaimsPrincipal可以包含多个ClaimsIdentity。当管道中存在多个Cookie中间件时,通过AuthenticationScheme进行区分。
在ClaimsIdentity中除了AuthenticationScheme外还有两个比较重要的属性,UserType和RoleType,其中UserType指定了用户验证类型,RoleType指定可角色验证类型。意思就是如果我指定了RoleType为”RoleName”,那么在进行角色认证时就会寻找Claims中所有的Type为”RoleName”的值,并检查其中是否包含了Authorize中指定的RoleName。不过.NET Core中自带了ClaimTypes,可以直接使用。例如角色类型就是ClaimTypes.Role。如果添加角色时用的自带的ClaimTypes.Role,那么在创建ClaimsIdentity时就不需要显示指定RoleType了,默认角色认证就是使用ClaimTypes.Role。
关于Cookie中间件的添加,是通过Startup中Configure方法中的app.UseIdentity扩展方法实现的。这个扩展方法实际上添加了多种Cookie识别方式。在后面我在写自己的用户认证管理时只用一种。
0x04 自己写用户认证管理
了解了用户认证的过程,我们可以自己写认证管理来代替Identity组件了,同样分为数据库操作和认证业务逻辑。数据库相关就不多说了,都写到了IdentityRepository类,只有很简单的数据操作。为了方便使用了Dapper,数据库用的Sqlite。程序在启动时会检查数据库表,没有会自动创建空表。
认证服务也比较简单就都写到了IdentityService类,提供了注册和登录操作,注销太简了直接写在了Action里。为了方便没有提供角色管理页面,如果要测试角色认证功能,需要手动去数据库添加Role,然后在UserRoles中给用户添加Role。
登录:
注册:
注销:
具体示例可以到:
https://github.com/durow/NetCoreStudy
只是为了测试,逻辑上很多问题,比如用户密码明文存储。重点看过程:)
0x05 写在最后
第一次接触Web应用,很多概念都不是很了解。就拿Cookie认证用户来说,我之前的只知道通过Cookie识别用户,一直以为是收到Cookie后再从数据库或缓存中查出相应的权限信息。不过看了自带的Cookie中间件代码后才知道认证信息是直接存在Cookie中的,这样只要解密后反序列化就可以了。Identity这个程序集涉及了很多其它程序集(Security、HttpAbstraction等等),看得我很晕,最后总算搞明白了一些,很多细节也没去深究,文中内容有的基于代码,有的基于个人理解,有错误希望大家嘴下留情。
.NET Core中的认证管理解析的更多相关文章
- [转].NET Core中的认证管理解析
本文转自:http://www.cnblogs.com/durow/p/5783089.html 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用 ...
- .Net Core中自定义认证实现
一.起因 最近项目中需要对项目同时支持JWT认证,以及自定义的认证校验方式认证.通过对官方文档了解,得到认证实现主要通过继承IAuthenticationHandler 或 Authenticatio ...
- asp.net core 2.1认证
asp.net core 2.1认证 这篇文章基于asp.net core的CookieAuthenticationHandler来讲述. 认证和授权很相似,他们的英文也很相似,一个是Authenti ...
- .net core 中的经典设计模式的应用
.net core 中的经典设计模式的应用 Intro 前段时间我们介绍了23种设计模式,今天来分享一下 asp.net core 种我觉得比较典型的设计模式的应用 实例 责任链模式 asp.net ...
- 如何在ASP.NET Core 中使用IHttpClientFactory
利用IHttpClientFactory可以无缝创建HttpClient实例,避免手动管理它们的生命周期. 当使用ASP.Net Core开发应用程序时,可能经常需要通过HttpClient调用Web ...
- ASP.NET Core中的OWASP Top 10 十大风险-失效的访问控制与Session管理
不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: https://dotnetcoretutorials.com/201 ...
- ASP.NET CORE中使用Cookie身份认证
大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cook ...
- C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入
C# 嵌入dll 在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形 ...
- ASP.NET Core 中jwt授权认证的流程原理
目录 1,快速实现授权验证 1.1 添加 JWT 服务配置 1.2 颁发 Token 1.3 添加 API访问 2,探究授权认证中间件 2.1 实现 Token 解析 2.2 实现校验认证 1,快速实 ...
随机推荐
- 网站定位之---根据IP获得区域
记得以前做一个培训机构网站时候需要定位,那时候用的搜狐的api,不是很精准. demo:https://github.com/dunitian/LoTCodeBase/tree/master/NetC ...
- Git命令总结
本文转载自345大神.... 查看原文 先上个图形化界面GIT工具 SourceTree下载链接 windows版 1.8.3 & Mac版 2.2.4 链接: http://pan.baid ...
- GOF23设计模式之单例模式
·核心作用: -保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. ·常见应用场景: -Windows的Task Manager(任务管理器)就是很典型的单例模式 -Windows的Recy ...
- iOS自定义model排序
在开发过程中,可能需要按照model的某种属性排序. 1.自定义model @interface Person : NSObject @property (nonatomic,copy) NSStri ...
- SharePoint 2016 必备组件离线安装介绍
前言 SharePoint 必备组件安装,一直以来都是SharePoint安装过程中的最大的坑,尤其是不能联网的服务器.博主在这里简单介绍一下离线安装过程,并附组件包下载以及安装命令,并且在windo ...
- 仿陌陌的ios客户端+服务端源码项目
软件功能:模仿陌陌客户端,功能很相似,注册.登陆.上传照片.浏览照片.浏览查找附近会员.关注.取消关注.聊天.语音和文字聊天,还有拼车和搭车的功能,支持微博分享和查找好友. 后台是php+mysql, ...
- DevExpress - 使用 GaugeControl 标尺组件制作抽奖程序 附源码
前不久,公司举办了15周年庆,其中添加了一个抽奖环节,要从在读学员中随机抽取幸运学员,当然,这个任务就分到了我这里. 最后的效果如下,启动有个欢迎页面,数据是来自Excel的,点击开始则上面的学号及姓 ...
- 第14章 Linux启动管理(1)_系统运行级别
1. CentOS 6.x 启动管理 (1)系统运行级别 ①运行级别 运行级别 含义 0 关机 1 单用户模式,可以想象为Windows的安全模式,主要用于系统修复.(但不是Linux的安全模式) 2 ...
- oracle常用的快捷键
最近在开发过程中,遇到一些麻烦,就是开发效率问题,有时候其他同事使用PLSQL 编程效率明显高于自己,观察了好久,才发现他使用PLSQL 已经很长时间了而且,他自己也在其中添加了好多快捷方式, 1.登 ...
- C#编写windows服务,多服务为什么只启动一个(ServiceBase.Run)
https://zhidao.baidu.com/question/380395667.html //多服务一个宿主程序时必须注间以下要点: Service1的ServiceName 必须 Insta ...