自从上次的《偷懒小工具 - Excel导出》发布之后,看阅读量还能够,就决定继续分享一下其余方面的帮助类。html
风格仍是相似的极简风,登陆方法,调用的代码尽可能超过三行,而后搞定一切。源代码参考文章最下方。git
a.baidu.com 中。a 是二级域名,baidu 是一级域名。一样的一级域名是能够共享Cookie的。github
不一样一级域名,由于同源策略缘由,不能共享Cookie。也就是跨域算法
例如:微信扫码登陆,就是这种跨域的实用例子跨域
a.baidu.com 和 b.baidu.com 是能够共享cookie,也就是同域。缓存
www.baidu.com 和 www.qq.com 就属于跨域。安全
SSO 单点登陆,主要就是使用统一的身份验证模块,而后各网站共享身份验证。微信
也就是只登陆一次,其余网站都可免登录。cookie
关于身份验证方面,各位若有疑惑可自行百度。或者看一下,我记录的 《ASP.NET身份认证》函数
(是给本身看的可能有些乱)
由于同源策略的问题,因此同域和跨域方法实现差距比较大。
我这边根据同域和跨域,这两种不一样状况,分享两个帮助类。
这两个帮助类,互相独立。各位按照本身的需求选择查看使用。
(由于就一我的精力有限,白天还要上班,没有进行太多测试)设计不合理或者BUG,确定会有一些。
首先,看一下同域的流程图。
再看一下,跨域的流程图
看着,很简单吧。我相信大家确定能够看懂,我就不做解释了。下面看使用。
这里WebConfig,采用了以下的配置。
用户认证网站,直接使用~/Login.aspx 指向本身的登陆页面。
其余网站,使用 “认证网站地址”+?link+“本网站地址”。这种方式,来进行登陆后的跳转。
共同一级域名的状况。可使用SSOGeneralSameDomain类,进行登陆。
其中,Login就是用户登陆方法。一共两行代码。name 参数是你须要保存的数据。
其中,Index方法,能够得到你保存的用户名。(这里为了方便使用的明文用户名)
WebForm登陆方式是同样的,这里不作过多描述。
调用 SSOGeneralSameDomain.LogUp(); 可进行用户注销。
此时你的网站,就能够共享身份验证了。
不一样一级域名的状况。可使用SSOGeneralCrossDomain类,进行登陆
须要传递:保存的数据、Cookie名称、保存时长
须要传递:认证网站地址、Cookie名称、保存时长
此时,你就能够完成跨域单点登陆了。可是注意,认证网站,还须要调用一个验证方法。
分析
同域的思路比较简单,也相对来讲比较好实现。有两点要考虑的(若是有其余办法,请留言)
Request 操做:由于Mvc和WebForm的Request,存在于两个不一样的类(HttpContextBase和Page)。
这个找了半天,也没有想到能公用的办法,因而就用抽象工厂来搞了一下。
跳转问题:由于Forms身份认证的ReturnUrl参数,只能拿到文件,而不能拿到网址。因此无法跳转到对应网站。
这个我在博问上试着问了一下,结果有一个大哥说:你要这么多干啥,没啥用。当时我就懵逼了!!!
后来,没有找到什么好办法,就用的笨办法,也就是使用link进行跳转。
作法
这两个问题解决了,咱们接下来看看代码。仍是向上次同样,一步一步来讲一下。
作Request和Response操做封装
首先,建立一个抽象类,而后把须要的方法封装一下,接着定义Page和HttpContext两个子类,继承实现
作同域单点登陆的类
1. 首先,分析一下每一个登陆,都须要名字和过时时间,那么这俩字段上移。 确定都得有登陆方法,那么方法上移。
这里字段Set 私有,也是安全性的考虑。我在初始化的时候,就传递这两个参数。
2. 接着,建立 SSOGeneralSameDomain 类,继承抽象类。
定义私有字段,Operation用来执行操做。构造函数中对这个字段进行赋值。
实现抽象类的LogIn方法。这个方法只有三步:1.建立Forms认证票据。2.保存到Cookie中。3.成功后跳转。
CreateTicket 和 CreateCookie 方法逻辑很是简单,我就不说明了。说一下跳转逻辑。
有link 找link,没有找ReturnUrl,再没有直接跳转到根目录。 至此登陆作完了。
3. 最后,作注销和获取内容方法。这边为了方便,使用静态类实现的。
注销都是固定的方法,获取内容,就是拿Cookies。而后解密
同域的帮助类,至此就算完成了。
跨域真的是比较纠结的一点,由于我懒,因此通常都是先上网找相关文章。
发现,文章有用的很是少。一些伪跨域的特别多,有些卡卡卡说一大堆,结果发现不一样的是二级域名。
还有就是使用 接口,来回传信息的。由于我想作帮助类,用接口的话就耦合在一块儿了。不太想用。
PS:找了一天,最后烦躁了不找了,开始本身想本身研究。
分析
实际上同域须要处理的地方,就是传递凭证。接收到凭证之后,就会进行本地存储,因此传递是终点。
跨域须要考虑的点,就比较多了,除了同域的问题还有如下几点:(若是有其余办法,请留言)
Cookie不能共享:使用Token做为凭据传递,可根据Token获取保存信息。
持久化:提供持久化接口,任何方式只要知足此接口便可。我这里提供了Http缓存和Cookies方法。
登陆和认证:流程跟上面的图差很少。主要开放五个方法:
LogIn(登陆)、LogInClient(其余网站登陆)、ValidationToken(认证)、GetUserData(获取登陆内容)、LogUp(注销)
作法
1. 首先,仍是跟同域同样作Operation 而后Page 和 HttpContextBase继承这个Operation
2. 由于会有凭证的传递,因此咱们还须要一个加密。这里,我给出一个接口,并给出了DES加密的实现方法。
各位能够按照本身想进行的加密逻辑,自行扩展。
3. 持久层也是必不可少的,用来存放已经登陆的用户信息。这里也是给出的接口。并给出了Cookie 和 Cache的操做方法
各位能够按照本身想实现的持久层,进行处理。
CreateToken 生成凭证的这个方法。我这边采用最简单的GUID进行生成的,这种无规律的是没有办法伪造的。
SetToken的UserData,使用的就是上方的加密认证。
我以为只要涉及到HTTP传递,就确定能拦截,因此重点应该是怎么不让他破解。加密算法,各位能够自行实现。
public class SSOToken
{
public string UserData { get; set; } public string Token { get; set; } public DateTime OverdueTime { get; set; } }
持久层存储模型,就使用这个必不可少的几个字段进行存储。
4. 跨域单点登陆类,由于这个类比较复杂,因此我不想提太多公共方法或字段。
建立SSOGeneralCrossDomain类,咱们把参数都做为属性提出来,而后把接口也进行提取。
咱们看一下LogIn 登陆方法是如何实现的。
这个方法,是认证中心点击保存之后执行的方法。
先进行SetToken 把登陆信息存到持久层。而后返回对应的Token。
接着进行GetRedirectUrl。这个方法获取咱们登陆成功后,将要跳转的地址。
接下来的,跟同域的状况同样。这里就很少说了。咱们如今已经实现了,认证中心的登陆。接下来,咱们制做其余网站的登陆。
其余网站,使用此功能,也要定义本身的Login.aspx页面,只是在这个页面调用这个方法。
咱们先判断,是登陆仍是认证。好比:咱们没有登陆,打开网站A,这种状况就是登陆。网站A登陆后,跳转到网站B,这种状况就是认证
接下来咱们验证Token,这一步很重要。这一步能够把网站引导到认证中心,或者自动认证。
接下来,就是显而易见的 解密、本地存储了。很简单很少讲了。
GetUserData 和 LogUp。一个是获取本地Cookie,一个是注销登陆(跟同域操做同样)
至此,咱们的单点登陆,所有搞定。接下来,咱们进行测试。
首先,咱们建立两个认证中心。一个MVC的,一个WebForm的。而后Web建立2个网站,MVC建立1个。用来作跳转。
Authorize 认证中心,使用的是MVP 的PV模式。首先咱们给Web相关的网站,定义统一的Web.Config
同域状况下,Web1\2 登陆地址均指向 Authorize
接下来,在登陆后调用方法
咱们在 Web1 里面写一下获取方法 和 注销
这个时候,咱们Web1设为启动项。而后就能够测试了。具体页面,我就不粘贴了。能够参考下方源码
跨域须要在各个应用底下,建立本身的Login.aspx登陆页面。而后调用这个方法,或者你建立主页调用同样。
Web1网站 调用方法以下
加载内容以下
Authorize网站,调用方法以下
在Initialize 初始化的时候,添加验证方法。这样能够接受其余网站发送的验证请求。
在登陆页面,直接调用登陆方法便可。
具体测试项目,都在Github上。各位能够自行下载。