本章主要内容有:
● 实现基于微软帐户的第三方身份验证
● 实现双因子身份验证
● 验证码机制html
在微软提供的ASP.NET MVC模板代码中,默认添加了微软、Google、twitter以及Facebook的帐户登陆代码(虽然被注释了),另外针对国内的一些社交帐户提供了相应的组件,全部组件均可以经过Nuget包管理器安装:算法
从上图中看到有优酷、微信、QQ、微博等组件,其中一些是微软提供的,一些是其它开发者提供的。而本文将使用微软帐户为例来介绍如何实现一个第三方登陆。
注:本章主要代码参考ASP.NET MVC模板代码,因此在文章中只列出关键代码,其他代码与模板中的彻底一致。数据库
在开发以前首先须要经过Nuget安装Microsoft.Owin.Security.MicrosoftAccount:安全
另外就是须要去微软的开发者中心使用微软帐户建立一个本身的应用信息https://apps.dev.microsoft.com/,并保存应用的ID以及密钥用于对身份验证中间件进行配置:微信
建立过程以下:
1. 点击添加应用按钮,进入应用程序注册页面,填写应用名称并点击Create按钮(注:因为我已经有一个名称为My Blog的App,因此下面的Test App的建立流程仅仅是用于演示,后续的身份验证明际上是使用以前建立的My Blog):app
2. 在后续页面中点击生成新密码来生成密钥(注:该密码只显示一次,须要在弹出框中复制并保存下来):ide
3. 添加平台:点击添加平台按钮,添加一个Web平台,并在平台的重定向Url中填入本地调试的地址信息(注:必定须要启动HTTPS而且地址后须要添加signin-microsoft,VS能够在项目的属性中开启SSL,并设置SSL的URL):加密
4. 保存更改。3d
在上一篇文章中介绍了,第三方帐户身份验证除了特定帐户身份验证中间件外,还须要添加一个消极模式的外部Cookie身份验证中间件,因此首先须要在项目的Startup文件中添加一下代码:调试
而后再在该中间件后加入微软身份验证中间件(注:中间件顺序会影响处理流程,微软身份验证中间件必须在外部Cookie中间件后),并设置上面建立的应用ID及密钥:
如今能够说应用中已经支持微软的帐户身份验证了,可是在应用中还未提供微软身份验证的入口,以及登录后用户信息的补全等功能。
1. 在页面上添加验证入口,在Login页面上加入如下代码,经过AuthenticationManager来获取全部的第三方身份验证方式,并生成对应连接:
2. 在AccountController中添加ExternalLogin Action方法(注:该方法主要目的是调用AuthenticationManager的Challenge方法来触发微软身份验证中间件的ResponseChallenge方法来完成页面的跳转):
其中ChallengeResult是一个自定义的ASP.NET MVC Reuslt类型:
3. 加入第三方验证后的回调方法ExternalLoginCallback,该回调方法是获取第三方身份验证后的用户信息,而后在本地数据库中查找该用户,若是存在那么登陆成功,不然须要对该用户信息进行补全。
4. 添加第三方帐户信息补全页面及Action方法,其中action方法接收到补全的用户信息后完成用户注册功能,但要注意的是第三方帐户没有密码,仅仅是在AspNetUserLogins表中添加了第三方验证的信息:
运行结果:
1.访问登陆页面出现Microsoft的按钮(注:必须使用HTTPS地址才能正常的使用微软身份验证):
2. 点击微软身份验证按钮后,跳转到微软帐户登陆页面:
3. 完成登陆后,因为是第一次登陆,因此会跳转到信息补全页面:
输入邮箱后将登陆成功:
数据库中的信息:
上图中能够看到无密码,而后在Login表中有一条数据:
Identity的双因子身份验证明际上是Identity的一个内置功能,为何说是内置呢?由于只须要实现信息的发送(如邮件、短信等),而后再对Identity中的SignInManager进行简单的配置而后添加一些用于发送、填写验证码的页面就能够完成。因此首先须要完成的就是实现信息发送功能。
注:这里信息发送功能使用将信息写到硬盘的方式模拟。
1. 实现信息的发送:
在ASP.NET MVC默认的模板中就为咱们建立了以下代码:
默认的邮件及短信发送器,只不过它没有实现,仅仅是返回了一个空值,如今使用写硬盘的方式将信息写到硬盘上:
2. 完成UserManager的双因子验证配置:
三个关键点:1. TokenProvider,它用来生成验证码。2. 信息格式。3. 信息发送服务。
3. 在身份验证管道中加入双因子验证中间件:
两个中间件前者用于处理二次验证,后者用于记住登陆状态,下次访问系统时自动登陆。
4. 添加验证码发送方式选择以及验证码填写页面及相应的Action方法(代码略)。
5. 在数据库中将演示用的用户信息改成启用二次验证(注:模板代码中有用于管理我的信息的功能,此处省略了实现,直接经过修改数据数据的方式开启用户的双因子验证、添加电话号码等):
6. 运行结果:
登陆后须要选择验证码发送方式:
选择后点击提交按钮,页面调整到验证页面的同时,指定的文件中生成了须要的验证码:
填写验证码后点击提交按钮,则登陆成功:
注:双因子验证也能够应用到第三方帐户的登陆方式上,双因子验证只与用户有关与身份验证方式无关。
对于双因子验证来讲,它实际上就是在普通验证或第三方帐户验证的基础上增长了验证码的发送和验证两个环节,那么对于验证码这个主体Identity是如何来维护的呢?
在上面的介绍中,有一个环节就是须要经过对UserManager进行配置以支持双因子验证的消息发送、消息生成等等:
根据这个代码看来XXXTokenProvider是专门用来维护验证码的,而XXXService是用来发送的,因此这里将对TokenProvider进行说明,了解验证码是如何维护的:
上图是TokenProvider相关的一个简单类图,从类图中能够看出TokenProvider其实是实现了一个名为IUserTokenProvider的接口,该接口中有4个方法,它们的做用分别是:
● GenerateAsync:根据UserManager以及User信息来生成一个令牌(Token)。
● IsValidProviderForUserAsync:判断这个Token提供器对这个用户是不是有效的(若是使用短信验证,可是该用户没有设置手机号,那么就是无效的)。
● NotifyAsync:当Token生成后调用该方法通知用户,如短信或邮件通知。
● ValidateAsync:用于验证Token是否有效。
而TotpSecutityStampBasedTokenProvider是一个实现了IUserTokenProvider接口的,经过用户安全戳生成验证码的生成器:
从代码中能够看到该算法是基于rfc6238(TOTP: Time-Based One-Time Password Algorithm,基于时间的一次性密码算法) https://tools.ietf.org/html/rfc6238,而后经过用户的安全戳以及GetUserModifierAsync方法生成特定的信息熵来完成密码加密,关于信息熵可参考:https://www.zhihu.com/question/22178202,上面将生成后的令牌执行ToString("D6")是将其转换为一个6位数字的字符串。
而Token的验证方式和生成差很少都是经过用户安全戳和信息熵来验证提交的验证码(它其实是一种hash算法):
以上已经解释了最初验证码的生成和验证的问题,因此对于EmailTokenProvider和PhoneNumberTokenProvider只是对熵的生成、对Provider的有效性(是否存在Email或电话号码)、通知方式进行了修改,下面是PhoneNumberTokenProvider相关代码:
本章主要是使用代码的形式实现了ASP.NET中的第三方验证和双因子验证,文中的代码都来自ASP.NET MVC的模板,因此文中仅仅是对关键的代码进行了介绍,一些细节的内容可参考完整代码。其中第三方验证使用的是微软帐户,若是有环境支持能够尝试国内的微信、QQ等身份验证。
另外在文章最后对验证码的生成和校验代码进行了分析,知道了它是基于Hash算法的信息加密、验证的机制来实现的。
ASP.NET MVC基于Identity提供了很是完善、强大的用户管理和身份验证功能,除了以上介绍的之外还有帐户锁定、注册邮箱或短信验证功能,基本上已经涵盖了如今开发经常使用的功能,但这些功能被一个模板实现了,因此ASP.NET强大吗?