前面的文章中为My Blog加入了文章的管理功能(ASP.NET没有魔法——ASP.NET MVC使用Area开发一个管理模块),但是管理功能应该只能由“作者”来访问,那么要如何控制用户的访问权限?也就是当用户访问管理功能时需要对用户进行身份验证,对于用户来说身份验证也就是登录,即提供一个登录界面,通过账号密码的形式登录后就可以访问受限制的内容。

  本文将从以下几个方面介绍ASP.NET MVC是如何实现用户身份验证的:
  ● Web中的身份验证
  ● ASP.NET的Identity组件介绍
  ● ASP.NET MVC中使用Identity——组件安装
  ● ASP.NET MVC中使用Identity——EntityFramework
  ● ASP.NET MVC中使用Identity——注册功能的实现
  ● ASP.NET MVC中使用Identity——登录功能的实现
  ● ASP.NET MVC中使用Identity——身份验证功能的实现

  注:本文的目的是介绍在已存在的项目中如何使用Identity组件来添加用户注册、登录和验证的功能,所以内容会比较细琐,后续会对Identity中比较关键的点进行介绍,如用户密码的加解密、Cookie的生成与验证,Identity与Owin等等方面进行深入分析介绍。

Web中的身份验证

  Web应用作为一种特殊的应用软件系统,它是基于HTTP协议的,由于HTTP的独特性(无状态)所以每一次访问都是独立的、不携带上一次请求信息的,所以现在常用的身份验证方式都是通过Cookie或者url查询字符串的形式来保存“状态”信息,达到每次访问服务器,服务器都能“知道”用户身份的目的。

  ASP.NET作为一个Web程序的开发框架,提供了一些身份验证的方式如From验证,它通过用户提到的服务器的用户特征(如用户名、密码等)生成一个加密的Cookie信息,后续请求中将带着该Cookie信息证明用户身份。下图是博客园中的Cookie信息:

  

  随着软件系统的发展,普通的身份验证已经不能满足系统的需求,如登录时候的二次验证、第三方账号登录、用户授权等。所以ASP.NET又针对这些需求开发了Identity组件(Identity的前身为MemberShip)。

ASP.NET的Identity组件介绍

  Identity用来快速为ASP.NET应用程序搭建一个完善的身份验证系统。它可以支持ASP.NET框架下的所有程序身份验证,并通过EF Code First来支持用户数据的持久化,并集成OWIN来解耦不再依赖System.Web。另外它还支持第三方账号登录、短信/邮件二次验证等高级功能。

  Identity主要的组件如下:

  ● Microsoft.AspNet.Identity.Core:Identity的核心类库,实现了身份验证的核心功能,并提供了拓展接口。
  ● Microsoft.AspNet.Identity.EntityFramework:Identity数据持久化的EF实现。
  ● Microsoft.AspNet.Identity.OWIN:基于Identity的OWIN身份验证插件,它代替了原有的Form验证。
  ● Microsoft.Owin.Host.SystemWeb:Owin的IIS宿主,将IIS的接收到的请求转入Owin处理。

ASP.NET MVC中使用Identity——组件安装

  1. 通过Nuget来安装Microsoft.AspNet.Identity.EntityFramework(已包含Microsoft.AspNet.Identity.Core):

  

  2. 安装Microsoft.AspNet.Identity.OWIN:

  

  3. 安装Microsoft.Owin.Host.SystemWeb:

  

ASP.NET MVC中使用Identity——EntityFramework

  上面介绍过Identity支持EF的code first,那么自然就会想到实体与DBContext,那么在Identity中它们是怎么实现的呢?

  1. Identity中的实体:

  以User信息为例,Microsoft.AspNet.Identity.Core类库中提供了User的核心接口:

  

  它的具体实现则位于Microsoft.AspNet.Identity.EntityFramework中:

  

  除了User外,Identity还定义了Role、UserClaim、UserLogin以及UserRole这些实体,如下图:

  

  2. Identity中的DBContext:

  在Microsoft.AspNet.Identity.EntityFramework中提供了一个IdentityDbContext类型(注:其它IdentityDbContext的泛型实现是用于对实体进行拓展的,如果没有拓展需求,那么使用非泛型类型即可)。

  

  3. 在ASP.NET MVC项目中使用Identity提供的DbContext(注:本例中的代码大部分参考ASP.NET MVC默认模板代码):

    1). 继承IdentityDbContext<TUser>类型,实现自己的DbContext(注:通过继承来使用Identity的DbContext可以灵活的根据需求来改变DbContext及其实体的配置)。

    

    2). 使用enable-migrations命令启用自动迁移,并在BlogIdentityDbContext中设置自动将数据库更新至模型最新版本:

    自动迁移(即无需使用add-migration命令来添加数据库结构变更):

    

    自动将数据库更新到模型最新版本:

    

    注:本例基于My Blog的MySQL数据库实现,在更新数据库时为避免一下错误,所以在OnModelCreating中加入了两个对象的主键。

    

    3). 在web.config中加入MySQL的EF配置以及一个名称为"DefaultConnection"的连接字符串(因为上面的DbContext构造方法中指定了参数DefaultConnection):

    

     连接字符串:与BlogContext共用同一个数据库:

     

    注:此处要说明两点,第一是使用配置文件的形式来配置EF的MySQL配置原因是,MyBlog中没有引用EF MySQL的组件,无法使用代码,只有等编译完成后把所有依赖的程序集复制到bin目录下,启动程序时通过配置文件解析。第二点是现在在整个解决方案中引入了两个DBContext,多个DBContext是可以共存的,只要对其进行正确的配置并提供正确的连接字符串。如果一个项目中有多个DBContext时,对其进行迁移操作就需要通过参数指定被操作的DbContext,可以参考这篇文章:http://www.cnblogs.com/Jack-Blog/p/4699596.html

    4). 可以执行update-database命令将DbContext同步到数据库中(因为设置了数据库自动同步,所以也可以等待后面运行程序时自动同步):

    

    

ASP.NET MVC中使用Identity——注册功能的实现

  在ASP.NET MVC中实现注册功能之前,先要了解一下Identity组件提供的业务逻辑“层”(注:这里说“层”仅仅是为了对应现有的项目结构,有数据层和逻辑层,其实在Identity中也是这样划分的,虽然它们都在同一个程序集中)。

  Identity中提供了RoleManager、UserManager等业务逻辑的实现类型,下图是UserManager的定义:

  

  从图中可以看出,它已经具有创建用户、添加角色等逻辑的实现,所以对于注册功能来说仅需要调用UserManager的对应方法即可。下面就介绍如何添加注册功能:

  1. 添加注册使用的ViewModel:

  

  2. 创建AccountController以及Register Action方法:

  

  注:UserManager依赖UserStore,UserStore又依赖于DbContext,也就是说业务逻辑依赖仓储,仓储又依赖数据库操作的实现。

  3. 创建View:

  

  4. 在布局页面中加入注册链接:

  

  5. 运行:

  

  

  数据库结果:

  

ASP.NET MVC中使用Identity——登录功能的实现

  登录功能的目的是对用户提交到服务器的用户名和密码进行验证,验证成功后生成一个包含用户信息的加密的字符串并以Cookie的形式返回到客户端。

  登录功能的实现方法与注册差不多就是添加视图模型、Action和View,然后在Action中调用Identity的用户验证方法即可:

  1. 创建ViewModel:

  

  2. 添加登录Action(注:sigInManager封装了登录的业务逻辑包括写Cookie):

  

  3. 添加View并在布局页面加入登录链接:

  

  

  4. 运行效果:

  

  

  注:现在还未添加访问的限制,所以登录与不登录其实上是一样的。

ASP.NET MVC中使用Identity——身份验证功能的实现

  用户完成登录操作后仅仅是在Cookie中多了一个用户信息,如果不对该信息进行验证那么这个信息是没有作用的,ASP.NET中没有魔法,它任何的操作都是有代码在后面支撑,那用于支撑Identity的身份验证的代码是什么呢?之前在介绍Identity时提到过它是通过Owin来与Web服务器解耦的,Owin它是Web服务器处理HTTP请求的一个规范,而它在IIS中是一个httpModule扩展(关于Owin后续会进行详细介绍)。总的来说在IIS中Owin以HttpModule的拓展方式,为HTTP的请求处理又添加了一个处理管道。

  那么Identity与Owin的集成实际上是在Owin的处理管道中,来读取请求数据中的登录后生成的Cookie并验证,实现的具体方式如下:

  1. 创建一个Owin Startup类文件:

  

  2. 在Configuration方法中添加Cookie验证的中间件,当未登录访问受限内容时自动跳转登录页面:

  

  3. 为需要限制访问的Controller添加Authorize特性:

  

  4. 在布局文件中添加逻辑判断,当登录成功后显示用户名,未登录时显示登录链接:

  

  5. 运行:

  访问受限页面admin/home/index(未登录将跳转):

  

  登录后能够访问被限制的内容:

  

  登录后的首页(由于样式问题”欢迎 admin“字符串与背景同色( ╯□╰ )):

  

小结

  本章主要内容是对ASP.NET 身份验证以及Identity进行了简要的介绍,然后解释了在ASP.NET MVC中是如何通过Identity实现用户的注册、登录和身份验证的。本例的代码主要参考并简化了默认的ASP.NET MVC带有独立身份验证的模板代码,所以如有需要可对照模板代码进行对比。

  另外要注意的是通过模板建立的注册、登录都是带有模型数据验证的,但本例中没有加入,关于模型的验证会在后续介绍。

参考:

  http://johnatten.com/2014/04/20/asp-net-mvc-and-identity-2-0-understanding-the-basics/
  https://docs.microsoft.com/en-us/aspnet/identity/overview/getting-started/adding-aspnet-identity-to-an-empty-or-existing-web-forms-project
  https://msdn.microsoft.com/zh-cn/library/azure/ms789031(v=vs.90).aspx
  http://www.cnblogs.com/dinglang/archive/2012/06/03/2532664.html
  http://www.cnblogs.com/xzwblog/archive/2017/05/10/6834663.html

本文链接:http://www.cnblogs.com/selimsong/p/7723827.html

ASP.NET没有魔法——目录

ASP.NET没有魔法——ASP.NET 身份验证与Identity的更多相关文章

  1. ASP.NET没有魔法——ASP.NET Identity 的“多重”身份验证

    ASP.NET Identity除了提供基于Cookie的身份验证外,还提供了一些高级功能,如多次输入错误账户信息后会锁定用户禁止登录.集成第三方验证.账户的二次验证等,并且ASP.NET MVC的默 ...

  2. ASP.NET没有魔法——ASP.NET MVC使用Oauth2.0实现身份验证

    随着软件的不断发展,出现了更多的身份验证使用场景,除了典型的服务器与客户端之间的身份验证外还有,如服务与服务之间的(如微服务架构).服务器与多种客户端的(如PC.移动.Web等),甚至还有需要以服务的 ...

  3. 从零搭建一个IdentityServer——聊聊Asp.net core中的身份验证与授权

    OpenIDConnect是一个身份验证服务,而Oauth2.0是一个授权框架,在前面几篇文章里通过IdentityServer4实现了基于Oauth2.0的客户端证书(Client_Credenti ...

  4. asp.net core 3.x 身份验证-3cookie身份验证原理

    概述 上两篇(asp.net core 3.x 身份验证-1涉及到的概念.asp.net core 3.x 身份验证-2启动阶段的配置)介绍了身份验证相关概念以及启动阶段的配置,本篇以cookie身份 ...

  5. ASP.NET没有魔法——ASP.NET Identity的加密与解密

    前面文章介绍了如何使用Identity在ASP.NET MVC中实现用户的注册.登录以及身份验证.这些功能都是与用户信息安全相关的功能,数据安全的重要性永远放在第一位.那么对于注册和登录功能来说要把密 ...

  6. ASP.NET没有魔法——ASP.NET MVC 过滤器(Filter)

    上一篇文章介绍了使用Authorize特性实现了ASP.NET MVC中针对Controller或者Action的授权功能,实际上这个特性是MVC功能的一部分,被称为过滤器(Filter),它是一种面 ...

  7. ASP.NET没有魔法——ASP.NET OAuth、jwt、OpenID Connect

    上一篇文章介绍了OAuth2.0以及如何使用.Net来实现基于OAuth的身份验证,本文是对上一篇文章的补充,主要是介绍OAuth与Jwt以及OpenID Connect之间的关系与区别. 本文主要内 ...

  8. ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(下篇)

    上一篇<ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)>文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这 ...

  9. ASP.NET没有魔法——ASP.NET MVC Razor与View渲染

    对于Web应用来说,它的界面是由浏览器根据HTML代码及其引用的相关资源进行渲染后展示给用户的结果,换句话说Web应用的界面呈现工作是由浏览器完成的,Web应用的原理是通过Http协议从服务器上获取到 ...

随机推荐

  1. 201521123048 《java程序设计》 第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1. ...

  2. 三分钟深入TT猫之故障转移

    结束了一周繁忙的工作,趁着周末,小编手中的键盘早已饥渴难耐了,想知道上期省略号中发生了什么有趣的故事么?且听小编娓娓道来,结尾有彩蛋. 目录 风月前场 梦回现实 模拟老鸨 会话机制 故障转移 总结 风 ...

  3. CoordinatorLayout的使用

    最近项目有一个需求,做出类似闲鱼鱼塘界面的效果.如下图: 所以想到用CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout去搭建此界面. Coor ...

  4. Mybatis源码解析-DynamicSqlSource和RawSqlSource的区别

    XMLLanguageDriver是ibatis的默认解析sql节点帮助类,其中的方法其会调用生成DynamicSqlSource和RawSqlSource这两个帮助类,本文将对此作下简单的简析 应用 ...

  5. 说下browserslist

    browserslist 是一个开源项目 见到有些package.json里会有如下的配置参数 "browserslist": [ "> 1%", &qu ...

  6. 实例讲解webpack的基本使用第一篇

    更新文章不容易,尤其是更新高质量的文章更加不易,因此为了节约时间,闲话就不多说了.关于webpack的介绍,webpack是用来干嘛的,这些基础概念性的东西,就不在此赘述,下面直接开始正题. webp ...

  7. http://codeforces.com/contest/349

    A. Cinema Line time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  8. Ubuntu16笔记本双显卡安装NVIDIA驱动

    blockquote { direction: ltr; color: rgb(0, 0, 0) } blockquote.western { font-family: "Liberatio ...

  9. Ionic3学习笔记(五)动画之使用 animate.css

    本文为原创文章,转载请标明出处 目录 前言 animate.css 的使用 animate.scss 的使用 1. 前言 animate.css 是一款强大的.跨浏览器的预设CSS3动画库,内置了很多 ...

  10. Log4net日志使用教程-控制台、文本、数据库三种记录方式

    一.log4net简介: 1. Log4net的优点: 几乎所有的大型应用都会有自己的用于跟踪调试的API.因为一旦程序被部署以后,就不太可能再利用专门的调试工具了.然而一个管理员可能需要有一套强大的 ...