单点登录通用类
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单点登录通用类相关的知识,希望对你有一定的参考价值。
说明
自从上次的《偷懒小工具 - Excel导出》发布以后,看阅读量还可以,就决定继续分享一下其他方面的帮助类。
风格还是类似的极简风,登录方法,调用的代码尽量超过三行,然后搞定一切。源代码参考文章最下方。
同域和跨域
a.baidu.com 中。a 是二级域名,baidu 是一级域名。同样的一级域名是可以共享Cookie的。
不同一级域名,因为同源策略原因,不能共享Cookie。也就是跨域
例如:微信扫码登录,就是这种跨域的实用例子
a.baidu.com 和 b.baidu.com 是可以共享cookie,也就是同域。
www.baidu.com 和 www.qq.com 就属于跨域。
单点登录
SSO 单点登录,主要就是使用统一的身份验证模块,然后各网站共享身份验证。
也就是只登录一次,其他网站均可免登陆。
关于身份验证方面,各位如有疑惑可自行百度。或者看一下,我记录的 《ASP.NET身份认证》
(是给自己看的可能有些乱)
因为同源策略的问题,所以同域和跨域方法实现差距比较大。
我这边根据同域和跨域,这两种不同情况,分享两个帮助类。
这两个帮助类,互相独立。各位按照自己的需求选择查看使用。
(因为就一个人精力有限,白天还要上班,没有进行太多测试)设计不合理或者BUG,肯定会有一些。
流程图
首先,看一下同域的流程图。
再看一下,跨域的流程图
看着,很简单吧。我相信你们肯定可以看懂,我就不作解释了。下面看使用。
使用步骤
配置
这里WebConfig,采用了如下的配置。
用户认证网站,直接使用~/Login.aspx 指向自己的登录页面。
其他网站,使用 “认证网站地址”+?link+“本网站地址”。这种方式,来进行登录后的跳转。
同域
共同一级域名的情况。可以使用SSOGeneralSameDomain类,进行登录。
- 首先,需要你自行制作一个登录界面,自行进行用户名和密码的验证
- 调用如下方法。
其中,Login就是用户登录方法。一共两行代码。name 参数是你需要保存的数据。
其中,Index方法,可以获得你保存的用户名。(这里为了方便使用的明文用户名)
WebForm登录方式是一样的,这里不做过多描述。
调用 SSOGeneralSameDomain.LogUp(); 可进行用户注销。
此时你的网站,就可以共享身份验证了。
跨域
不同一级域名的情况。可以使用SSOGeneralCrossDomain类,进行登录
- 首先,需要自行制作一个登录界面。这个没法省略,或者你直接用我示例代码的登录。
- 认证网站,调用LogIn方法。其他网站,调用LogInClient方法。
需要传递:保存的数据、Cookie名称、保存时长
需要传递:认证网站地址、Cookie名称、保存时长
此时,你就可以完成跨域单点登录了。但是注意,认证网站,还需要调用一个验证方法。
思路和过程
同域
分析
同域的思路比较简单,也相对来说比较好实现。有两点要考虑的(如果有其他办法,请留言)
- Request 和 Response 的操作问题
- 其他网站的登录后跳转问题
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不能共享,如何验证信息
- 如何处理登录用户的持久化
- 登录和认证要用什么形式展现
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,这一步很重要。这一步可以把网站引导到认证中心,或者自动认证。
- 首先,我们认为没有传递凭证 就是需要登录。UserData 是已经认证完毕的内容。
- 我们判断是否同域,因为Cookie只有在一个域下才可以调用。
- 我们把当前的地址信息封装,引导到认证中心进行认证。
- 没有进行验证的都会在这一步卡住。
接下来,就是显而易见的 解密、本地存储了。很简单不多讲了。
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上。各位可以自行下载。
源码地址:https://github.com/chenxygx/SSOGeneral
以上是关于单点登录通用类的主要内容,如果未能解决你的问题,请参考以下文章