ASP.NET Core 之 Identity 入门(三)

转自:http://www.cnblogs.com/savorboard/p/aspnetcore-identity3.html

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 : class
    where TRole : class
{
    // 这个就是被 Identity 使用的
    services.AddAuthentication(options =>
    {
        // This is the Default value for ExternalCookieAuthenticationScheme
        options.SignInScheme = new IdentityCookieOptions().ExternalCookieAuthenticationScheme;
    });

    // 注册 IHttpContextAccessor ,会用到
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    // Identity services
    services.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 系列也结束了,感谢支持的朋友们。如果你对 .NET Core 感兴趣可以关注我,我会定期在博客分享关于 .NET Core 的学习心得。


本文地址:http://www.cnblogs.com/savorboard/p/aspnetcore-identity3.html
作者博客:Savorboard
欢迎转载,请在明显位置给出出处及链接

时间: 2024-10-16 04:59:33

ASP.NET Core 之 Identity 入门(三)的相关文章

ASP.NET Core 之 Identity 入门(一)

参考页面: http://www.yuanjiaocheng.net/ASPNET-CORE/core-identity.html http://www.yuanjiaocheng.net/ASPNET-CORE/core-authorize-attribute.html http://www.yuanjiaocheng.net/ASPNET-CORE/core-identity-configuration.html http://www.yuanjiaocheng.net/ASPNET-COR

[转]ASP.NET Core 之 Identity 入门(一)

本文转自:http://www.cnblogs.com/savorboard/p/aspnetcore-identity.html 前言 在 ASP.NET Core 中,仍然沿用了 ASP.NET里面的 Identity 组件库,负责对用户的身份进行认证,总体来说的话,没有MVC 5 里面那么复杂,因为在MVC 5里面引入了OWIN的东西,所以很多初学者在学习来很费劲,对于 Identity 都是一头雾水,包括我也是,曾经在学 identity 这个东西前后花了一个多月来搞懂里面的原理.所以大

ASP.NET Core 入门教程 4、ASP.NET Core MVC控制器入门

原文:ASP.NET Core 入门教程 4.ASP.NET Core MVC控制器入门 一.前言 1.本教程主要内容 ASP.NET Core MVC控制器简介 ASP.NET Core MVC控制器操作简介 ASP.NET Core MVC控制器操作简介返回类型简介 ASP.NET Core MVC控制器操作简介返回类型示例 ASP.NET Core MVC控制器参数映射逻辑说明 ASP.NET Core MVC控制器参数映射/获取示例 2.本教程环境信息 软件/环境 说明 操作系统 Win

ASP.NET Core 3.0 入门

原文:ASP.NET Core 3.0 入门 课程简介 与2.x相比发生的一些变化,项目结构.Blazor.SignalR.gRPC等 课程预计结构 ASP.NET Core 3.0项目架构简介 ASP.NET Core MVC 简介 Blazor SignalR Web API gRPC 发布 一. 创建项目 dotnet core 本质上是控制台应用 1. DI 依赖注入(Dependency Injection) IoC 容器(Inversion of Control)控制反转 注册(服务

【目录】ASP.NET Core 2.1 入门教程

ASP.NET Core 2.1 快速学习.入门系列教程,这个入门系列教程为了帮助大家快速上手ASP.NET Core. 本教程包含且不限于: 使用VS Code开发ASP.NET Core应用 ASP.NET Core MVC 开发(路由.控制器.视图) EF Core(连接MySQL,基础数据库操作示例) NLog日志组件使用 ASP.NET Core 中间件等等 本教程示例代码:https://github.com/ken-io/asp.net-core-tutorial https://

ASP.NET Core学习之一 入门简介

一.入门简介 在学习之前,要先了解ASP.NET Core是什么?为什么?很多人学习新技术功利心很重,恨不得立马就学会了. 其实,那样做很不好,马马虎虎,联系过程中又花费非常多的时间去解决所遇到的“问题”,是简单的问题,对,就是简单,就是因为觉得简单被忽略的东西,恰恰这才是最重要的. 1.学习资料 首先,介绍下哪里可以获得学习资料 英文官网,最好的文档,英语得过硬 https://docs.microsoft.com/en-us/aspnet/core/ 可惜当年英语就是马马虎虎过来的,所以找了

Pro ASP.NET Core MVC 6th 第三章

第三章 MVC 模式,项目和约定 在深入了解ASP.NET Core MVC的细节之前,我想确保您熟悉MVC设计模式背后的思路以及将其转换为ASP.NET Core MVC项目的方式. 您可能已经了解本章中讨论的一些想法和约定,特别是如果您已经完成了高级ASP.NET或C#开发. 如果没有,我鼓励你仔细阅读 - 深入地理解隐藏在MVC背后的东西可以帮助你在通读本书时更好地与MVC框架的功能联系起来. MVC的历史 模型视图控制器模式起源于20世纪70年代后期,来自施乐PARC的Smalltalk

【视频】ASP.NET Core MVC 2.* 入门

比较初级的入门教程,网址在B站:https://www.bilibili.com/video/av33728783/ 内容如下: 1. ASP.NET Core 简介和开发工具 2. ASP.NET Core 启动相关的基础知识 3. 使用Nuget & NPM 安装,优化第三方库 4. 配置MVC和其它中间件 5. 环境和Tag Helpers 1 6. Tag Helpers 2 7. 配置参数和View Component 8. 发布 9. 部署到Ubuntu (Nginx, 监控, HT

ASP.NET Core (二):入门

上一篇:ASP.NET Core(一):简介 下一篇:(待续) 英文原版:Getting Started 1. 安装 .NET Core 2. 创建 .NET Core 项目 在命令提示符窗口输入命令: mkdir aspnetcoreapp cd aspnetcoreapp dotnet new 3. 更新 project.json 文件,将 Kestrel HTTP 服务器程序包作为依赖添加到文件中 { "version": "1.0.0-*", "b