专栏首页菩提树下的杨过老生常谈:利用Membership实现SSO(单点登录)

老生常谈:利用Membership实现SSO(单点登录)

虽然有一些现成的第三方解决方案比如:OpenID,Passport,SpaceCard等都还不错,但是要么就是收费的(passport),要么就是有点用不习惯(比如OpenID),另外中途跳到一个界面完全不相同的第三方站点上输入,用户感觉也不太放心。

当然博客园和csdn上也有不少人已经给出了相应的解决方案,但是一圈看下来,虽然思路都行得通,貌似就是没找到不同主域名下直接利用Membership实现的例子。

那么还是自己“造轮子”弄一个简陋一点的方案吧,其实只要用过Membership的朋友都知道“用户是否已经登录”以及“用户当前的role是什么”等问题的判断依据就是检测客户端有没有(当前要访问)网站(所在域)的cookie票据,如果各子站都在同一个主域下,这么问题很容易解决,只要设置各子域cookie的domain为统一值即可,但如果各子站的主域名不同,这招就失效了(出于安全考虑,浏览器设计时就约定不同主域的cookie不能互访),所以问题的关键是:如何能让用户在某个域成功登录后,自动把本域下的cookie票据同步复制到其它域下!

另外还有用户注销问题,当用户从一个分站注销时其它分站如何注销?其实把上面的思路反过来,也能找到问题的关键:即一个域下的cookie票据清除后,如何能让其它域下的cookie票据也能清除!

根本这个思路,大概整理了一个流程图:

当然还有一些因素要考虑:比如传递敏感参数(比如用户名)时应该加密;同时各分站专用于接收票据和清除票据的页面,如何防止非法访问等等。此外,最好还要求各分站使用同一套统一的用户名/密码表。(当然如果各分站已经有各自的用户数据了,也有办法解决,比如可以新建一套新的统一帐号/密码库,原来各自的分站用户表上加一个字段,映射到新库帐号表的唯一字段)。

示例代码:

1.解决方案结构图

说明:

Passport:认证中心,用于统一登录和注销的类似passport站点

SiteA:站点A,其中admin需要登录才能访问(规则在web.config中配置),passport目录下的login.aspx/loginout.aspx分别用于接收认证中心发来的票据,以及清除票据

SiteB:站点B,结构代码完全同SiteA相同,仅为了与SiteA比较效果用

WebHelper:工具辅助类

2.技术要点:

(a)Cookie同步问题:因为cookie是基于浏览器的,所以直接用代码以Post或Get方式模拟访问SiteA中的/passport/login.aspx以logout.aspx时,并不能正确生成Cookie或清除Cookie,因此我采用了一个变通的办法(隐藏的iframe)来模拟浏览器访问这二个页面

(b)为了尽量使用Membership的功能,少写代码,同时保留membership通过web.config配置目录访问权限的风格,在passport项目中,分别针对各个站点新建A,B...等分站目录,目的仅仅是让ReturnUrl=/Admin/Default.aspx能自动变成类似ReturnUrl=http://www.SiteA.com/Admin/Default.aspx,以便在页面跳转时不需要额外处理

(3)即使是用iframe来实现跨域读写Cookie,默认情况下,如果用户IE浏览器的“隐私”级别设置为中(及中以上)时,浏览器仍然会阻止iframe跨域设置Cookie(所谓的“同域同源”原则,即:当前浏览器的url以及各frame/iframe里面的页面,如果在同一个域名,就能正常实现cookie的读写,否则禁止。单从这一点看,IE其实要比FF之流安全),所以需要在PassPort以及联盟站点的IIS-->Http头中设置相同的P3P协议值(目的是告诉IE:这一组站点相互之间是“朋友”,不要“阻挡”!),具体办法有二种(任选一种即可):

2.1-直接写代码:Response.AddHeader("P3P","CP=\"CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR\"");  把这一行加入要执行Cookie读写的页面的Page_Load事件第一行(注:“CP=”后面的值可以随便设置,只要是一个其它人不知道的string即可,相当于一个密钥)

2.2-IIS站点属性->HTTP头->添加-->自定义HTTP头为 P3P-->自定义HTTP头值为 CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR”-->保存

3.示例代码说明

示例中对于参数的加密采用了Enterprise Library 4.1的加密模块,所以需要安装Enterprise Library才能编译通过

欢迎转载,但请注明来自“菩提树下的杨过”

示例代码下载地址:http://files.cnblogs.com/yjmyzz/SSO.rar

2013/10/3 更新:

利用HttpModule自动拦截机制,把原来各分站的Login.aspx/LoginOut.aspx这些都去掉了,全都在HttpModule拦截处理,同时用script 引用,代替了原来的iFrame机制,新的示例代码地址:http://files.cnblogs.com/yjmyzz/SSO.zip

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • UrlReferrer为空的问题?

    官方解释:获取有关客户端上次请求的 URL 的信息,该请求链接到当前的 URL。 1.也就是说,如果用Request.Redirect之后,再用Request....

    菩提树下的杨过
  • Ado.Net连接池的速度测试

    晚上闲来无事,突然想测试一下Ado.Net连接池带来的连接速度提升,写了以下代码: using System; using System.Configura...

    菩提树下的杨过
  • mac上mysql8.0以tar.gz方式手动安装

    官网地址: https://dev.mysql.com/downloads/mysql/

    菩提树下的杨过
  • 记一次 sed 悲剧

    今天,一个 Linux 命令失误让我失去了博客的所有 Markdown 文档。很坑的命令,一共 77 篇 Markdown 文档,里面的内容全部变为了 omme...

    莲花海
  • IDEA报错Error:Module 'shop-common' production: java.lang.IndexOutOfBoundsException

    本来项目是正常的,编译、运行、启动都是OK的,但是在一次电脑重启后,出现了以上这个问题:Error:Module 'shop-common' productio...

    我是十三
  • Java---俄罗斯方块小游戏

    去年就已经学了这个技术了,一直没去写,现在抽个时间写了个俄罗斯方块游戏。 只有简单的新游戏,暂停,继续,积分功能。简单的实现了俄罗斯的经典功能。 不介绍...

    谙忆
  • 从0到1,马蜂窝大交通团队如何构建高效研发流程体系?

    ? ? “旅游之前,先上马蜂窝” 已经成为许多人习惯性的选择。 2019年5月,马蜂窝完成了新一轮融资,金额达2.5亿美元。这也标志着通过集内容、社区、交易为...

    腾讯技术工程官方号
  • 6. 简单又复杂的“运算符”,建议你看一哈

    昨天的《5. 很“迷”的字符与字符串》初稿本来很短的,但是我觉得内容太少了,就加了一些,结果好像就变得特别多〒▽〒。

    谭庆波
  • 从0到1,马蜂窝大交通团队如何构建高效研发流程体系?

    ? “旅游之前,先上马蜂窝。”已经成为许多人习惯性的选择。 2019年5月,马蜂窝完成了新一轮融资,金额达2.5亿美元。这也标志着通过集内容、社区、交易为一体...

    TAPD敏捷研发
  • 你需要知道的混合云最佳实践

    SDNLAB

扫码关注云+社区

领取腾讯云代金券