前面的文章中为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. Day-18: 电子邮件

    ---恢复内容开始--- 假设要从**@163.com发送邮件到**@sina.com,会经过下面几个过程: 首先,你得使用邮件代理软件(也就是MUA:Mail User Agent),例如Outlo ...

  2. python基础之socket

    一.osi七层 完整的计算机系统由硬件,操作系统,软件组成. 互联网的核心就是由一堆协议组成,协议就是标准,如全世界通信的标准就是英语. 如果把计算机比作人,那么互联网协议就是计算机界的英语,所有计算 ...

  3. OSGi-入门篇之服务层(03)

    前言 作为OSGi框架中最上面的一层,服务层带给了我们更多的动态性,并且使用了大家或多或少都曾了解过的面向服务编程模型,其好处是显而易见的. 1 什么是服务 简单的说,服务就是“为别人所做的工作”,比 ...

  4. 【Debian 8.8】Java 8 安装以及环境变量配置

    事实上可以分为简单的三个步骤: 下载 JDK 压缩包 解压压缩包 配置环境变量 需要注意的是: 所有命令默认在 root 权限下进行! 演示环境是 Debian 8.8 64位 (阿里云学生机) 1. ...

  5. Spring在JSP页面使用ServletContext

    在 JSP 页面使用Application 可以 看到使用的是WebApplicationContextUtils 而不是WebApplicationContext.ROOT_WEB_APPLICAT ...

  6. webpack + vue + node 打造单页面(入门篇)

    1.node下载地址:http://nodejs.cn/download/,安装完成检查node和npm版本 2.淘宝镜像 : npm install cnpm -g --registry=https ...

  7. RabbitMQ消息队列之二:消费者和生产者

    在使用RabbitMQ之前,需要了解RabbitMQ的工作原理. RabbitMQ的工作原理 RabbitMQ是消息代理.从本质上说,它接受来自生产者的信息,并将它们传递给消费者.在两者之间,它可以根 ...

  8. Ensemble Learning: Bootstrap aggregating (Bagging) & Boosting & Stacked generalization (Stacking)

    Booststrap aggregating (有些地方译作:引导聚集),也就是通常为大家所熟知的bagging.在维基上被定义为一种提升机器学习算法稳定性和准确性的元算法,常用于统计分类和回归中. ...

  9. BZOJ2431_逆序对数列_KEY

    转自YXDs 题目传送门 不知道今天是怎么了,可能是空调吹多了吧,一直不在状态,连递推题我都做不来了--(扎Zn了老Fe--) 然而,不管环境如何恶劣,我们仍要努力学习,为了自己的明天而奋斗.(说的好 ...

  10. AngularJS 1.3中的一次性数据绑定(one-time bindings)

    点击查看AngularJS系列目录 谈谈AngularJS 1.3中的一次性数据绑定(one-time bindings) 不久之前,AngularJS 1.3版本正式发布,其中添加了很多的性特性,同 ...