转载地址:http://blog.sina.com.cn/s/blog_4f52c70d0100uz51.html

最近在使用sina微博时,经常性交替使用 weibo.com 和 t.sina.cm.cn进入我的微博。发现当我在t.sina.com.cn中登录之后,直接切换至weibo.com,这时候在 weibo.com是已经登录的,当我在weibo.com进行注销之后,再切换至 t.sina.com.cn,这时候在t.sina.com.cn也已经是注销的状态了。 

   对于SSO的实现方案及其机制,早已经不是什么新鲜的技术了,从微软为.net提供的passport机制到java中开源的JBossSSO、Oracle OpenSSO及经典的 YaleCAS等等之类的开源或一些商业SSO中间件都不失为作为单点登录实现的选择。当然一些企业也会选择自己实现一套适合自己轻量级方案,如采用SESSIONID转递或SESSION同步复制之类的。 可以看得出SSO的价值也是具大的,就拿sina来说吧,增加weibo.com域名之后,对于用户来说来说没有任何影响,即使你在t.sina.com.cn中进行登录,可以无缝在两域名之间随意切换,对于它推广weibo.com无非是大大的益处。 

   由于近年来一直在使用Yale的CAS作为SSO的方案,觉得SINA的SSO与Yale-CAS有很多异曲同工之妙,于是便对SINA的SSO进行分析,其中的细节处理还是很值的学习的。当然,由于分析看到的SINASSO处理都只是一些表现或表面上的东西,再加上其大部分关键的ssojs都已经被压缩,及SERVER端的实现机制也只是靠自己的经验及结合CAS的的一些原理进行猜测。其实本文应该叫 <CASSSO与SINA SSO的实现对比分析>更比较贴切。 
   
   好吧,进入正题。 

  • Sina SSO之分析篇

   首先是进入t.sina.com.cn,提交用户名及密码进行登录,通过 Firebug可以看到它通过类似Aajx POST到了http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.12),如下图所示: 
     

   不难看出,其http://login.sina.com.cn/sso/login.php 就是类似是 CAS 中的Server,对sina的所有应用系统提供的统一登录入口。上面的参数中有一个service参数,了解 CAS的GG应该知道 cas在登录的时候除了username 和 password同样也有一个 service参数,其CAS该参数含义是子应用系统的服务名标识及登录成功之后所跳转的地址。当然,sina这里使用了"miniblog"作为微博的服务名,估计他在sso-server端对 miniblog 与登录成功之后的地址进行映射,如miniblog=http://t.sina.com.cn/,这样就避免了CAS-client中转入service=decodeURIComponent('http://t.sina.com.cn')之类的做法了。 

  这里的登录与CAS做法一致,将登录验证提交至统一的认证中心进行验证处理,从而避免了跨子域和全域的问题。 验证成功之后路转的路径就是service所向的地址,验证失败之后则返回至当前登录页。下面就SSO中的一些登录方面的核心问题做一些分析,看看SINA和CAS分别是如何处理的: 

    1.如何授权某个子系统允许其在sso-server进行登录验证呢,类似cas-server中的login-ticket; 
       对于cas来说,在首次进入  /cas/login页时,会产生一个一次性的login-ticket,也就是说在提交登录验证前必须向服务器请求一个login-ticket,在登录提交时,需要将用户名及密码以及login-ticket进行提交至cas-server端,cas-server端确定login-ticket有效后才会对用户名及密码进行认证。 
       看看sina如何处理的吧,继续看firebug: 
              以上截图是当我首次进行 t.sina.com.cn时,通过ajax/jsonp的方式发起的一个请求,可以看到返回的callback函数中的 json 串中包含了nonce:"SXK19N"的属性,参数名的汉译是“一次”或“一次性”的意思,估计这里的nonce就是login-ticket,为再一次确实,我再试着提交登录看看,看它是否将该参数POST过去: 
        
      果然不出所料,nonce:"SXK19N"作为参数提交过去了,证明所猜测的应该是正确的。 

  2.比如验证码跨域跨服务器导致从session无法获取的问题,我们曾经遇到过; 
       貌似sina登录没有涉及到验证码之类的东西,当你多次登录失败之后,它采用的是“您的登录过于频繁,请稍后再试吧”,这种方案确实比验证码要好的多,而且还避免了上面的说的问题。 

    3.当我登录失败了,/sso/login.php 如何将登录的错误信息返回给t.sina.com.cn并让它进行显示呢,如果我登录成功了/sso/login.php通过什么方式通知t.sina.com.cn呢,因为它这里使用的是ajax方式登录? 
      对于这方面,cas的处理是将错误信息以参数的方式返回给 client-login,如登录失败,重定向地址:http://cas-client.com?errocode=0,如果登录成功,则直接 重定向至 service中的url,并生成ST给客户端,表示其已经在cas-server登录成功了。 
      看看sina如何处理的吧,随便输入一个用户名密码,提交登录,继续通过firebug看看它的处理过程: 
   
       再看看t.sina.com.cn 中的html内容的变化: 
         
        
    以上图1中发生了两次请求,第一次登录验证是访问sso认证中心,它所返回response是一个html内容,第二次请求的地址: http://t.sina.com.cn/ajaxlogin.php framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=4038&amp;reason=���) 
    再结合以上图2信息,看到 html中发生了变化,创建了一个 id=ssoLoginFrame 的iframe,于是便可以得出,sina的登录并非原生的ajax方式,而是通过创建iframe来模拟提交不刷新的登录。也就是说,当用户点击登录提交时,这时候它会通过js创建iframe,将登录提效至该iframe中。 
        既然已经知道它登录是提交到iframe中,而非ajax方式,那么对于以上截图1中两个请求为什么返回的都是HTML内容就很容易解释了。再回到上面的问题,/sso/login是如何通知t.sina.com.cn登录失败了呢?首先在以上第一个截图中返回的 HTML包含了一段 javascript: 
       

Javascript代码
  1. location.replace("http://t.sina.com.cn/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=4038&reason=��¼�%A����Դ������Ƶ�������Ժ��ٵ�¼");  
location.replace("http://t.sina.com.cn/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=4038&reason=��¼�%A����Դ������Ƶ�������Ժ��ٵ�¼");

       location.replace的意思与location.href类似,同样都是改变当前的URL地址,具体区别及做法可以参考这里及这里。需要注意的这里所说的通过location.replace改变当前的URL其它并非改变t.sina.com.cn的地址,而是第二个截图里iframe中src的地址,因为这段HTML是在iframe中输出的。 
      在  locaiton.replace 的地址中包含了一个 retcode 及reason参数,估计这就是当前登录的错误信息。在上面第一个截图的第二个请求实际就是在iframe 中进行的location.replace操作后的跳转地址。关键看它输出的html内容: 
  

Html代码
  1. <html><head>  
  2. <script language='javascript'>  
  3. parent.sinaSSOController.feedBackUrlCallBack({"result":false,"errno":"4038","reason":"\u767b\u5f55\u5c1d\u8bd5\u6b21\u6570\u8fc7\u4e8e\u9891\u7e41\uff0c\u8bf7\u7a0d\u540e\u518d\u767b\u5f55"});</script></head><body></body></html>null  
<html><head>  <script language='javascript'>   parent.sinaSSOController.feedBackUrlCallBack({"result":false,"errno":"4038","reason":"\u767b\u5f55\u5c1d\u8bd5\u6b21\u6570\u8fc7\u4e8e\u9891\u7e41\uff0c\u8bf7\u7a0d\u540e\u518d\u767b\u5f55"});</script></head><body></body></html>null

    这段js是在 iframe中执行的,所以可以通过 parent 进行访问 t.sina.com.cn中的js,可以肯定parent.sinaSSOController.feedBackUrlCallBack 就是告诉 t.sina.com.cn当前已经登录失败了,并且将错误信息传至该入该callback了。至此,已经完成了 /sso/login.php 对t.sina.com.cn的信息传送。 新浪果然是有一手呀,在CAS中AJAX登录一直都是一个问题,而sina它巧妙的通过iframe+callback进行实现了。 
     接着,再看看它对于登录成功之后如何通知 t.sina.com.cn的吧,先看看登录成功之后 sina-sso-server会做什么,看firebug截图: 
       
      重点在于 set-Cookie:tgc=TGT-MTc4NTc0NzM0Mw==-1305003116-ja-D51B2EB107B79FC50D8CA424BFE08907; 哈哈,熟悉CAS的应该会很熟悉这个,没想到SINA的TGT与CAS的TGT不但参数命名,居然连生成的规则也一模一样,估计sina肯定是参考了cas的实现机制。关于TGT是什么或其作用可以参考:CAS总结之Ticket篇。另外还有一个就是当登录成功之后,sina-sso-server会将用户登陆名等等放在sina.com.cn根域的cookie中。 
      然后再看看登录成功之后 sina-sso-server所返回的response内容: 
       
      以下是从以上摘取JS部分: 
      

Javascript代码
  1. <script>  
  2. try{sinaSSOController.setCrossDomainUrlList({"retcode":0,"arrURL":["http:\/\/weibo.com\/sso\/crosdom?action=login&savestate=1305607916"]});}catch(e){}try{sinaSSOController.crossDomainAction('login',function(){location.replace('http://t.sina.com.cn/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=0');});}catch(e){}  
  3. </script>  
<script>  try{sinaSSOController.setCrossDomainUrlList({"retcode":0,"arrURL":["http:\/\/weibo.com\/sso\/crosdom?action=login&savestate=1305607916"]});}catch(e){}try{sinaSSOController.crossDomainAction('login',function(){location.replace('http://t.sina.com.cn/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=0');});}catch(e){}  </script>

    首先再次声明,以上firebug截图中的请求处理,并非 AJAX,而是在 t.sina.com.cn中放了一个iframe,输出的reponse都会至iframe当中.     
     以上的js主要重点在于: 
     

Javascript代码
  1. location.replace('http://t.sina.com.cn/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=0')  
location.replace('http://t.sina.com.cn/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=0')

    还是通过设置当前iframe中src地址,再看看跳转至http://t.sina.com.cn/ajaxlogin.php后的response内容吧: 
      
     返回用户信息(从cookie中获取的),并且还是类似上面的做法,通过 parent.sinaSSOController.feedBackUrlCallBack回调t.sina.com.cn中的js,告诉它这个用户已经登录成功了。 
     于是t.sina.com.cn便进行跳转至 t.sina.com.cn/dengers中,从而实现登录。 
      
     整体的处理流程如下: 
      

     4.当我在t.sina.com.cn中登录后,切换至weibo.com,weibo.com我应该也是已经登录的,如何做到呢? 
      对于这个问题,CAS中的处理就是,当我进入 weibo.com的时候,马上跳转至 /cas/login,然后在login中判断cookie是否存在TGT,如果存在,并确定其有效性后,则认为你已经登录,并为你生成一个ST,将ST作为ticket参数使其重定向至weibo.com?ticket=TG-xxxx 并登录。 
     看看sina怎么处理的吧,首先我直接在t.sina.com.cn登录成功。然后再新建一个选项卡,输入weibo.com: 
      
     可以看得出,当我进入 weibo.com之后,sina并没有直接进入weibo.com的主页,而是马上重定向至: http://login.sina.com.cn/sso/login.php?url=http://weibo.com/&_rand=1305008634.5127&gateway=1&service=miniblog&useticket=1&returntype=META 与cas的做法确实一致。 再看看该 login.php的Response信息,主要是JS: 
      

Js代码
  1. <script type="text/javascript" language="javascript">  
  2. location.replace("http://weibo.com/sso/login.php?url=http://weibo.com/&ticket=ST-MTc4NTc0NzM0Mw==-1305008634-ja-694BA43623A3F72999AE7129A0572048&retcode=0");  
  3. </script>  
            <script type="text/javascript" language="javascript">             location.replace("http://weibo.com/sso/login.php?url=http://weibo.com/&ticket=ST-MTc4NTc0NzM0Mw==-1305008634-ja-694BA43623A3F72999AE7129A0572048&retcode=0");               </script>

    看到这里之后,不得不怀疑 SINA 的 SSO 是不是用的就是 CAS 啊!!不但连 TGT参数名一样,连ST规则及参数名也一模一样,其处理机制也十分相似。 
     到这里之后就与 CAS 的处理一样了,就不详细写了,可以参考 CAS相关文章。 

────────── 
PS:由于在分析过程中里面的很多SSO关键JS都压缩了,所以难免会存在误差。 不过SINA的SSO很多细节方面确实处理的很好,作为互联网应用的话,如果单纯的只是把CAS DOWNLOAD 下来,然后直接配配就用的话很多方面的处理还是很不到位的。 有时间我把我们CAS参考SINA 调整一下。 

  到这里,不得不说的一个事情就是,之前在分析淘宝cookie如何跨域获取时,大家都说出了一个taobao的jsonp实际存在一定的安全隐患。后面那个淘宝的GG看到之后加入Refer的判断。而现在,在分析的过程中发现新浪也有这样的问题,可以尝试一下,随便在本地建立一个html,引入jquery,然后使用下面的JS,就可以获取到sina中的登录邮箱名等信息,前提是你需要先在sina中登录: 
 

Js代码
  1. $.ajax({url: 'http://t.sina.com.cn/ajaxlogin.php?framelogin=0&callback=?&retcode=0', dataType:'jsonp',  
  2.                success:function(data){  
  3.                    alert(data.userinfo.userid);  
  4.                }});  
$.ajax({url: 'http://t.sina.com.cn/ajaxlogin.php?framelogin=0&callback=?&retcode=0',dataType:'jsonp',success:function(data){alert(data.userinfo.userid);}});

新浪微博单点登陆分析相关推荐

  1. 京东SSO单点登陆实现分析

    京东的sso流程: 初始访问状态: cookies: http请求: 1.在首页点击登陆,跳转至passport.360buy.com,给予验证cookie alc(可以试试在提交登陆信息前删除该co ...

  2. 鉴权,开放式授权,单点登陆

    鉴权,开放式授权,单点登陆 鉴权 鉴权(authentication)是指验证用户是否拥有访问系统的权利.传统的鉴权是通过密码来验证的.这种方式的前提是,每个获得密码的用户都已经被授权.在建立用户时, ...

  3. python如何实现模拟登录_超详细的Python实现新浪微博模拟登陆(小白都能懂)

    最近由于需要一直在研究微博的爬虫,第一步便是模拟登陆,从开始摸索到走通模拟登陆这条路其实还是挺艰难的,需要一定的经验,为了让朋友们以后少走点弯路,这里我把我的分析过程和代码都附上来. 首先,我们先用正 ...

  4. IM开发基础知识补课:正确理解前置HTTP SSO单点登陆接口的原理

    1.前言 一个安全的信息系统,合法身份检查是必须环节.尤其IM这种以"人"为中心的社交体系,身份认证更是必不可少. 一些PC时代小型IM系统中,身份认证可能直接做到长连接中(也就是 ...

  5. 08-微服务版单点登陆系统(SSO)实践

    文章目录 单点登陆系统简介 背景分析 单点登陆系统概述 单点登陆系统解决方案设计 单点登陆系统初步设计 服务设计 工程结构设计 SSO父工程创建及初始化 创建父工程 父工程pom文件初始配置 系统基础 ...

  6. 09-微服务版的单点登陆系统设计及实现(2105~2106)

    文章目录 简介 背景分析 单点登陆系统 快速入门实践 工程结构如下 创建认证授权工程 添加项目依赖 构建项目配置文件 添加项目启动类 启动并访问项目 自定义登陆逻辑 业务描述 定义安全配置类 定义用户 ...

  7. 海波龙(Oracle Hyperion)单点登陆问题记录

    Oracle海波龙套件已经多年未更新,按Oracle官方文档实施单点登陆启用之后,SmartView工具通过专用链接方式无法登陆系统. 在抓包逆向分析之后 定位到HspSmartViewServlet ...

  8. 五、微服务版单点登陆系统(SSO)

    微服务版单点登陆系统(SSO)实践 文章目录 微服务版单点登陆系统(SSO)实践 一.单点登陆系统简介 1. 背景分析 2. 单点登陆系统概述 3. 单点登陆系统解决方案设计 二.单点登陆系统初步设计 ...

  9. 微服务版单点登陆系统(SSO)

    单体架构中的用户的状态的存储是如何实现的? 单点登陆系统概述 单点登录,英文是 Single Sign On(缩写为 SSO).即多个站点共用一台认证授权服务器,用户在其中任何一个站点登录后,可以免登 ...

  10. 09-微服务版单点登陆系统(SSO)实践

    目录 单点登陆系统简介 背景分析 单点登陆系统概述 单点登陆系统解决方案设计 单点登陆系统初步设计 服务设计 工程结构设计 SSO父工程创建及初始化 创建父工程 父工程pom文件初始配置 系统基础服务 ...

最新文章

  1. C++ JsonCpp 使用(含源码下载)
  2. P12 离散控制系统-《Matlab/Simulink与控制系统仿真》程序指令总结
  3. DM8168的McSPI/McASP/McBSP接口
  4. vim 使用中的一些错误[omnifunc未设置错误]
  5. vs2010中moc文件生成方法
  6. 后通用芯片时代: 专用芯片兴起背后的经济学
  7. python爬虫库教程_Python爬虫Selenium库详细教程
  8. PyTorch中常用Module和Layer的学习笔记~
  9. 砸115亿元入局!后知后觉的欧洲重金建设AI,为赶中超美
  10. 设计模式笔记(21)---备忘录模式(行为型)
  11. 无线短距通信技术标准:WIFI,蓝牙,ZigBee
  12. R 保存包含中文的 eps 图片--showtext
  13. tensorflow模型部署与python java API线上调用
  14. 图灵奖得主亲授!深度学习视频课程精选
  15. 关于形而上学与形而下学之区别及关系
  16. 分享优秀品牌平面广告创意作品的创意密码
  17. Photoshop教程实例讲解
  18. 轨物范世:华为手机的影像哲学
  19. learn.log - 进程管理器fastcgi原理及fastcgi_param详解
  20. PDPS软件:机器人可达性测试功能介绍与使用方法

热门文章

  1. 关于耦合度以及低耦合度的必要性
  2. 苹果保修期查询_苹果手机维修为什么这么贵?
  3. RationalDMIS 2020 网络报表/网络编程连接设置
  4. 商业虚拟专用网络技术一
  5. PDF可以修改吗,如何在PDF上修改文字
  6. 推荐几个比较好的软件测试博客论坛
  7. C语言---学生奖学金评定系统设计
  8. linux显卡驱动与opengl,NVIDIA率先发布OpenGL 3.0 Linux驱动
  9. 洛谷 P5713 【深基3.例5】洛谷团队系统 C语言
  10. Footprint 8月月报 DeFi市场多点开花,9月是否会迎来下一个爆发点