ASP.NET Core 之 Identity 入门(三)

前言

在上一篇文章中,我们学习了 CookieAuthentication 中间件,本篇的话主要看一下 Identity 本身。

最早2005年 ASP.NET 2.0 的时候开始, Web 应用程序在处理身份验证和授权有了很多的变化,多了比如手机端,平板等,所以那个时候为了适应这种变化就引入了ASP.NET Membership,但是随着时间的发展一些社交网站或者程序聚集了大量的用户,比如Facebook,Twitter,QQ等,这个时候用户希望能够使用他们在这些社交站点身份来登陆当前网站,这样可以免除注册这些琐碎而又必要的操作,用户也不必记住大量的账户密码。

又随着互联网的发展,越来越多的开发者不只是关注具体业务代码的编写,转变为开始关注应用程序代码的单元测试,这已经是开发者关注的核心。所以在2008年,ASP.NET 团队引入了 MVC 框架,这样来帮助开发者很方便的构建单元测试,同时开发者希望他们的 Membership 系统也能够做到这一点。

基于以上,ASP.NET Identity 应运而生。

Identity 要解决的问题

很多开发人员说他们不愿意使用Identity,自己实现要方便的多,OK,那么需求来了?以下就是我针对此次任务给你提出来的需求。

身份系统

  • 可以同时被所有的ASP.NET 框架使用(Web MVC,Web Forms,Web Api,SignalR)

  • 可以应用于构建 Web, 手机,存储,或者混合应用。

能够对用户资料(User Profile)很方便的扩展

  • 可以针对用户资料进行扩展。

持久化

  • 默认把用户信息存储在数据库中,可以支持使用EF进行持久化。(可以看到,EF 其实只是Identity的一个功能点而已

  • 可以控制数据库架构,更改表名或者主键的数据类型(int,string)

  • 可以使用不同的存储机制(如 NoSQL,DB2等)

单元测试

  • 使WEB 应用程序可以进行单元测试,可以针对ASP.NET Identity编写单元测试

角色机制

  • 提供角色机制,可以使用不同的角色来进行不同权限的限制,可以轻松的创建角色,向用户添加角色等。

要支持基于Claims

  • 需要支持基于 Claims 的身份验证机制,其中用户身份是一组Claims,一组Claims可以比角色拥有更强的表现力,而角色仅仅是一个bool值来表示是不是会员而已。

第三方社交登陆

  • 可以很方便的使用第三方登入,比如 Microsoft 账户,Facebook, Twitter,Google等,并且存储用户特定的数据。

封装为中间件

  • 基于中间件实现,不要对具体项目产生依赖

  • 基于 Authorzation 中间件实现,而不是使用 FormsAuthentication 来存储cookie。

NuGet包提供

  • 发布为 Nuget 包,这样可以容易的进行迭代和bug修复,可以灵活的提供给使用者。

以上,就是我提出来的需求,如果让你来封装这样一个用户身份认证组件,你会不是想到以上的这些功能点,那针对于这些功能点你又会怎么样来设计呢?

下面来看一下 Identity 怎么样设计的吧。

Getting Started

抽丝剥茧,我们先从入口看一下其使用方式。 首先我们打开 Startup.cs 文件,然后添加如下代码:

public class Startup{    public void ConfigureServices(IServiceCollection services)    {services.AddDbContext<ApplicationDbContext>(options =>options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));services.AddIdentity<ApplicationUser, IdentityRole>(options => {options.Cookies.ApplicationCookie.AuthenticationScheme = "ApplicationCookie";options.Cookies.ApplicationCookie.CookieName = "Interop";}).AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();}    public void Configure(IApplicationBuilder app)    {        // 使用了 CookieAuthentication 中间件做身份认证app.UseIdentity();}
}

在 ConfigureServices 中,先是注册了数据库上下文,然后又 services.AddIdentity() 我们看一下里面都注册了哪些服务呢?

public static IdentityBuilder AddIdentity<TUser, TRole>(this IServiceCollection services,Action<IdentityOptions> setupAction)where TUser : classwhere TRole : class{    // 这个就是被 Identity 使用的services.AddAuthentication(options =>{        // This is the Default value for ExternalCookieAuthenticationSchemeoptions.SignInScheme = new IdentityCookieOptions().ExternalCookieAuthenticationScheme;});    // 注册 IHttpContextAccessor ,会用到services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();    // Identity servicesservices.TryAddSingleton<IdentityMarkerService>();services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();    // 错误描述信息services.TryAddScoped<IdentityErrorDescriber>();services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();    //身份当事人工厂services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();    //三大对象services.TryAddScoped<UserManager<TUser>, UserManager<TUser>>();services.TryAddScoped<SignInManager<TUser>, SignInManager<TUser>>();services.TryAddScoped<RoleManager<TRole>, RoleManager<TRole>>();if (setupAction != null){services.Configure(setupAction);}return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
}    

看了以上代码后,基本上知道了 Identity 他的设计的一个架构了,通过此结构我们也能够学习到我们自己封装一个中间件的时候,该怎么样来组织我们的代码结构,怎么样的利用 ASP.NET Core 给我们提供的依赖注入来更好的解耦,下面我们来看一下通过以上代码我们能够学到什么东西:

1、 在 public static IdentityBuilder AddIdentity<TUser, TRole>(this IServiceCollection services, Action<IdentityOptions> setupAction)这个扩展方法中,提供了一个参数 Action<IdentityOptions>,这个是干什么用的呢? 这个是我们在设计一个中间件的时候,有需要外部提供的参数,就会设计一个 Options 的类用来接受外部的参数,然后封装为一个Action委托的方式提供。在使用到的地方就可以以 IOption xxx 的形式注入进来使用了。

2、services.TryAddScoped<Interface,Implement>(),这个注册方式就是说,如果检测到DI容器里面已经有了当前要注册的Interface或者Service,就不会再次注册,没有才会注册进去。 那么为什么此处要这样用呢? 这是因为如果用户已经实现了此接口并且已经注册的容器当中的话,就使用用户注册的,而不是中间件自身的。用户就能很好的对中间件提供的功能进行自定义了,这就是OO中的多态性,这就是里氏替换原则。

3、如果你能理解第2条的话,那么你应该知道为什么会在服务中注册 错误描述信息 那个IdentityErrorDescriber 了吧,也能够解决你想提示账号密码错误,无奈Identity输出是英文问题的提示。

4、三大对象,这个是 Identity 的核心了,所以学习 Identity 的话,在看完博客 ASP.NET Core 之 Identity 入门(一,二)之后,学这三个对象就够了。

SignInManager: 主要处理注册登录相关业务逻辑。

UserManager: 处理用户相关添加删除,修改密码,添加删除角色等。

RoleManager:角色相关添加删除更新等。

有些同学可能很好奇,都没有依赖具体的数据库或者是EF,是怎么样做到的增删改查的呢?

这个时候,就需要几个 Store 接口派上用场了。以下是Identity中定义的Store接口:

  • IQueryableRoleStore

  • IQueryableUserStore

  • IRoleClaimStore

  • IRoleStore

  • IUserAuthenticationTokenStore

  • IUserClaimStore

  • IUserEmailStore

  • IUserLockoutStore

  • IUserLoginStore

  • IUserPasswordStore

  • IUserPhoneNumberStore

  • IUserRoleStore

  • IUserSecurityStampStore

  • IUserStore

  • IUserTwoFactorStore

有了这些接口之后,是不是豁然开朗了,原来 Identity 是通过这种方式实现的持久化机制,依赖抽象接口而不是依赖具体的细节实现,这就是面向对象中的依赖倒置原则呀。

Identity 和 EntityFramework

Identity 和 EntityFramework的关系,相信上个章节看懂了之后,就很容易明白了,对的,EF 只是针对于上述 Store 接口的实现,不信你看截图的源码:

Identity 打头的那些类文件都是定义的需要持久化的Entity对象,Store结尾的那些就是接口的实现啦。

第三方的 Identity 实现

除了 EF 是官方默认提供的持久化库之外,还有一些第三方的库,当然你也可以自己使用 ADO.NET 或者 Drapper 实现。

MangoDb 针对于 Identity 提供的实现: https://github.com/tugberkugurlu/AspNetCore.Identity.MongoDB

LinqToDB 针对于 Identity 提供的实现:https://github.com/linq2db/LinqToDB.Identity

总结

这篇博文写了蛮久的时间的,一方面是因为在构思怎么样的思路来让大家更好的理解,而不仅仅是使用。因为有太多的文章介绍Identity 的使用方式以及代码了,但是最后大家还是不会用。后来想到如果让别人想要理解你的库也好代码也好,让其知道诞生的背景是很重要的,因为这才是设计的初衷。另一方面是因为Connect() 2016 大会上,.NET Core 发布了 1.1 版本,除了把项目升级到1.1之外,也在学习1.1新的一些东西,以便更好给大家分享。

相关文章: 

  • ASP.NET Core 之 Identity 入门(一)

  • ASP.NET Core 之 Identity 入门(二)

  • ASP.NET Identity登入技术应用

  • Web API 基于ASP.NET Identity的Basic Authentication

  • ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇

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


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

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

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

相关文章

玩物得志Java笔试题_代码规范利器-CheckStyle

本期内容分为五个部分&#xff0c;阅读时长预估7分钟&#xff1a;使用背景CheckStyle使用意义CheckStyle安装与使用CheckStyle检查配置示例落地使用情况及效果使用背景玩物得志目前还处在一个狂奔业务的时期&#xff0c;开发一般都全力支撑业务的快速奔跑&#xff0c;没有太多的…

Json交互处理

Json交互处理 JSON简介 JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式&#xff0c;目前使用特别广泛。采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人阅读和编写&#xff0…

利用 async amp; await 的异步编程

一、异步编程的简介 通过使用异步编程&#xff0c;你可以避免性能瓶颈并增强应用程序的总体响应能力。 Visual Studio 2012 引入了一个简化的方法&#xff0c;异步编程&#xff0c;在 .NET Framework 4.5 和 Windows 运行时利用异步支持。编译器可执行开发人员曾进行的高难度工…

xml配置文件显示为文本文件问题

idea 新建的xml文件显示为文本问题 原因: 由于新建不带后缀名的文件的时候 idea会相对智能的让你选择 文件规则 解决: settings->File types 中找到对应的文件类型显示 ,把 你不小心添加的 正则 给去除就好了, 我这里的配置如下图 可以自己进行设置&#xff08;&…

.NET应用迁移到.NET Core--调查案例

上周已经发过三篇文章讲述做.NET 应用迁移到.NET Core的一般方法&#xff0c;具体内容请看&#xff1a; .NET应用迁移到.NET Core&#xff08;一&#xff09; .NET应用迁移到.NET Core&#xff08;二&#xff09;风险评估 .NET应用迁移到.NET Core&#xff08;三&#xff09;从…

Ajax前后端对接---Springmvc

Springmvc实现 实体类user Data AllArgsConstructor NoArgsConstructor public class User {private String name;private int age;private String sex;}我们来获取一个集合对象&#xff0c;展示到前端页面 RequestMapping("/a2") public List<User> ajax2(…

缓存在大型网站架构中的应用

缓存的基本知识 在整个计算机体系构造中&#xff08;无论是硬件层面还是软件层面&#xff09;&#xff0c;缓存都是无处不在的。 在计算机硬件构造中&#xff0c;由于两种介质的速度不匹配&#xff0c;高速介质在和低速介质交互时速度趋向低速方&#xff0c;这就导致了高速介质…

win10安装dockerx docker的常见命令 可以子腾讯云上做做练习

参考资料 https://www.jianshu.com/p/e8427d12b3e0 百度搜索 docker hub 可以查找 你需要的镜像 https://hub.docker.com/?utm_sourcegetting_started_guide&utm_mediumembedded_Windows&utm_campaignfind_whalesay https://blog.csdn.net/zzq060143/article/de…

Jexus 5.8.2 正式发布为Asp.Net Core进入生产环境提供平台支持

Jexus 是一款运行于 Linux 平台&#xff0c;以支持 ASP.NET、PHP 为特色的集高安全性和高性能为一体的 WEB 服务器和反向代理服务器。最新版 5.8.2 已经发布&#xff0c;有如下更新&#xff1a; 1&#xff0c;现在大部分网站已经部署HTTPS&#xff0c;大家对于安全越来越重视&…

php移动代码,移动专区周级收录如何提交 复制这段php代码即可

今天我们来讲解下“移动专区的周级提交”很多朋友都在使用移动专区(之前的熊掌号)进行提交&#xff0c;但是天级提交只给10个额度&#xff0c;需要我们不断提交10个才会有所增长&#xff0c;但是我们可以使用“周级提交”可以直接享受5万的数据提交&#xff0c;对于我们站点的收…

搭建高可用的rabbitmq集群 + Mirror Queue + 使用C#驱动连接

我们知道rabbitmq是一个专业的MQ产品&#xff0c;而且它也是一个严格遵守AMQP协议的玩意&#xff0c;但是要想骚&#xff0c;一定需要拿出高可用的东西出来&#xff0c;这不本篇就跟大家说 一下cluster的概念&#xff0c;rabbitmq是erlang写的一个成品&#xff0c;所以知道如何…

Mybatis+mysql动态分页查询数据案例——配置映射文件(HouseDaoMapper.xml)

<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace"houseDao" ><result…

手机钉钉在进行视频会议时怎么录屏

https://www.iefans.net/info/v1037168.html 钉钉在进行视频会议时怎么录屏 编辑&#xff1a;秩名2020-03-24 10:14:52 钉钉 类型&#xff1a;效率办公 语言&#xff1a;简体中文 安卓下载 扫一扫下载游戏 钉钉是一款很好用的学习办公软件&#xff0c;它的工呢很多&#xf…

Vue3学习(后端开发)

目录 一、安装Node.js 二、创建Vue3工程 三、用VSCode打开 四、源代码目录src 五、入门案例——手写src 六、测试案例 七、ref和reactive的区别 一、安装Node.js 下载20.10.0 LTS版本 https://nodejs.org/en 使用node命令检验安装是否成功 node 二、创建Vue3工程 在…

微软Ignite大会约起来

今年的微软Ignite技术大会今天开始了&#xff0c;要好好学习哦&#xff0c;提供直播地址&#xff0c;通过阅读原文链接可以直达直播地址 http://soft.zdnet.com.cn/special/microsoft_ignite_2016。 大会亮点 创新 IT 技术飞速发展促发了更多行业创新&#xff0c;因此您和您的企…

aria2c rpc php,aria2c 的基本配置,附带傻瓜式源码

经常需要配置&#xff0c;但是 每次都需要查找配置项的意义&#xff0c;所以索性写在这里&#xff0c;以便有个记录&#xff0c;下次无需查找。aria2c -d/Users/blueboz/Downloads \-c \-D \-laria.log \-j5 -k1M \-x16 -s16 \--file-allocationnone \--enable-rpc \--load-coo…

最全Windows下搭建go语言开发环境以及开发IDE

https://www.cnblogs.com/ynhmonster/p/8335797.html GO语言开发环境的搭建---Windows环境下 1、Golang下载 我是通过Golang中国下载的&#xff0c;因为去官网下载十分慢&#xff0c;甚至没有进度条。 下载地址&#xff1a; https://www.golangtc.com/download 我选择的是go1…

外媒:微信小程序顺应“APP中启动APP”的行业潮流

BI中文站 11月30日报道 上周&#xff0c;中国网络巨头腾讯的高级副总裁张小龙对外披露了一些照片&#xff0c;显示聊天工具微信开始整合“小程序”。这一功能可以让微信的用户在无需下载软件的基础上&#xff0c;使用各种互联网应用服务&#xff0c;极大扩展微信的功能。 据外媒…

SpringMVC(笔记)

MVC简介 普通的web项目每次都要进行手动的把jar包导进去&#xff0c;否则会报500&#xff0c;class not found [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VstjHhuz-1609824493673)(C:\Users\王东梁\AppData\Roaming\Typora\typora-user-images…

php 去掉url中的index.php,php 去掉url中的index.php

php去掉url中的index.php的方法&#xff1a;首先打开相应的代码文件&#xff1b;然后将if代码块嵌套在server代码块中&#xff1b;最后重启nginx服务器即可。本文操作环境&#xff1a;nginx1.0.4系统、PHP7.1版&#xff0c;DELL G3电脑nginx服务器去掉url中的index.php将if代码…