ASP.NET没有魔法——ASP.NET 身份验证与Identity
前面的文章中为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 身份验证与Identity的更多相关文章
- ASP.NET没有魔法——ASP.NET Identity 的“多重”身份验证
ASP.NET Identity除了提供基于Cookie的身份验证外,还提供了一些高级功能,如多次输入错误账户信息后会锁定用户禁止登录.集成第三方验证.账户的二次验证等,并且ASP.NET MVC的默 ...
- ASP.NET没有魔法——ASP.NET MVC使用Oauth2.0实现身份验证
随着软件的不断发展,出现了更多的身份验证使用场景,除了典型的服务器与客户端之间的身份验证外还有,如服务与服务之间的(如微服务架构).服务器与多种客户端的(如PC.移动.Web等),甚至还有需要以服务的 ...
- 从零搭建一个IdentityServer——聊聊Asp.net core中的身份验证与授权
OpenIDConnect是一个身份验证服务,而Oauth2.0是一个授权框架,在前面几篇文章里通过IdentityServer4实现了基于Oauth2.0的客户端证书(Client_Credenti ...
- asp.net core 3.x 身份验证-3cookie身份验证原理
概述 上两篇(asp.net core 3.x 身份验证-1涉及到的概念.asp.net core 3.x 身份验证-2启动阶段的配置)介绍了身份验证相关概念以及启动阶段的配置,本篇以cookie身份 ...
- ASP.NET没有魔法——ASP.NET Identity的加密与解密
前面文章介绍了如何使用Identity在ASP.NET MVC中实现用户的注册.登录以及身份验证.这些功能都是与用户信息安全相关的功能,数据安全的重要性永远放在第一位.那么对于注册和登录功能来说要把密 ...
- ASP.NET没有魔法——ASP.NET MVC 过滤器(Filter)
上一篇文章介绍了使用Authorize特性实现了ASP.NET MVC中针对Controller或者Action的授权功能,实际上这个特性是MVC功能的一部分,被称为过滤器(Filter),它是一种面 ...
- ASP.NET没有魔法——ASP.NET OAuth、jwt、OpenID Connect
上一篇文章介绍了OAuth2.0以及如何使用.Net来实现基于OAuth的身份验证,本文是对上一篇文章的补充,主要是介绍OAuth与Jwt以及OpenID Connect之间的关系与区别. 本文主要内 ...
- ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(下篇)
上一篇<ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)>文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这 ...
- ASP.NET没有魔法——ASP.NET MVC Razor与View渲染
对于Web应用来说,它的界面是由浏览器根据HTML代码及其引用的相关资源进行渲染后展示给用户的结果,换句话说Web应用的界面呈现工作是由浏览器完成的,Web应用的原理是通过Http协议从服务器上获取到 ...
随机推荐
- 201521123074 《Java程序设计》第11周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 Q1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) ...
- 【干货】教你如何利用fullPage.js以及move.js插件打造高端大气的网站效果!
前言: 如今我们经常能见到全屏网站,尤其是国外网站.这些网站用几幅很大的图片或色块做背景,再添加一些简单的内容,显得格外的高端大气上档次. 在学习过jQuery插件之后,才发现之前的很多网站特效完全可 ...
- String StringBuffer StringBuilder 之间的区别
StringBuffer与StringBuilder的区别: StringBuffer是jdk1.0版本出来的,线程安全,效率低 StringBuilder是jdk1.5版本出来的,线程不安全,效率高 ...
- Hello PyQt5
在 ubuntu 系统上 GUI 编程,PyQt5 是个不错的选择.首先,当然是安装 PyQt5 了.终端输入命令: pip3 install PyQt5 即可. 1. 建立一目录 x01.PyQtH ...
- Java中的HTTP通信技术详解
1.使用HTTP的Get方式读取网络数据 class ReadByGet extends Thread{ @Override public void run(){ URL url = n ...
- JQuery实现banner图滚动
前 言 jQuery是一个功能强大的库,提供了开发JavaScript项目所需的所有核心函数.很多时候我们使用jQuery的原因就是因为其使用插件的功能,然而,有时候我们还是 ...
- 笨鸟先飞之ASP.NET MVC系列之过滤器(01过滤器简介)
过滤器 什么是过滤器? 过滤器(Filter) 主要的作用大致可以理解为把我们的附加逻辑注入到MVC框架的请求处理. 在ASP.NET MVC的请求处理中一种有19个管道事件分别是 BeginRequ ...
- Python多线程练习(threading)
这几天学习python多线程的时候,试了几次thread模块和threading模块,发现thread模块非常的不好用.强烈不建议大家使用thread,建议使用threading模块,此模块对thre ...
- Easyui后台管理角色权限控制
最近需要做一个粗略的后台管理的权限,根据用户的等级来加载相应的菜单,控制到子菜单.使用的是Easyui这个框架. 1.我使用的mysql数据库.在这里我就建立四张表,角色表(tb_users),菜单表 ...
- Windows中的硬链接和软链接(hard link 和 Symbolic link)
先来了解一下Linux中的硬链接和软链接: Linux中的硬链接和软链接 Windows中的硬链接和软链接: 硬链接 从Windows NT4开始,NTFS文件系统引入了HardLink这个概念,它让 ...