我的日常

登录/注册
您现在的位置:论坛 盖世程序员(我猜到了开头 却没有猜到结局) 盖世程序员 > 如何实现SSO (单点登录)
总共48087条微博

动态微博

查看: 1696|回复: 0

如何实现SSO (单点登录)

[复制链接]
admin    

1244

主题

544

听众

1万

金钱

管理员

  • TA的每日心情

    2021-2-2 11:21
  • 签到天数: 36 天

    [LV.5]常住居民I

    管理员

    跳转到指定楼层
    楼主
    发表于 2014-12-24 14:39:59 |只看该作者 |倒序浏览
           SSO (Single-Sign-On) 即单点登录,在互联网应用中是多个站点通过一次登录即可访问所有产品,如Google所有产品通过 http://accounts.google.com/,百度所有产品统一登录地点是 http://passport.baidu.com/ 等,也有些产品是提供自己的登录界面,然后到统一入口验证。总之,就是要实现一次登录,处处登录。
    ) y; P1 p; m! K6 P1 q+ M/ t% V  L" K: n% q8 _4 R
            如果所有产品都是在同一主域下,那么只要把登录的标识信息存放到主域的 cookie 中,即可实现访问任一产品的页面时把登录信息传递到服务器,然后服务器根据该信息判断是否需要用户再次登录。虽然大多数公司的产品都是在同一个域名下,但有些还是独立域名的,这时就涉及到跨域问题,也是 SSO 的难点所在。
    ! e+ d0 u9 A6 B$ ]. h$ r0 W$ v' w/ S$ X& @4 e& O# L6 s1 u1 ~
            基本思路是在一个固定的入口登录,成功后返回一个 token,将这个 token 附带在跨域访问的某个文件上,该文件拿到这个 token 和服务器上存放的值比较,并获取对应的登录用户信息,然后设置登录标识 cookie,以此完成 SSO 登录。服务器上的 token 可以存在 memcache 等缓存中,或者通过 RPC 访问。
    * b, J! h8 G+ Q- a' C, m5 l, t6 m* W; ^& O* P8 p0 }- B1 x8 S
    通过查看现有网站,主要是百度和新浪的 SSO 实现方案(截至2013-7-31),来对 SSO 实现方式有一个详细的了解。! u( g  s& o& H7 X

      O, N! s! j8 j6 _百度的 SSO0 F. T+ l$ G' U, i9 ^  G

    % m0 R; }* d5 Y. @4 g: p7 m& ?       百度的很多产品都是在 baidu.com 这个主域名下,纳入到 SSO 的其他独立域名目前只有 hao123.com(很讨厌这个网站,一不小心就会在装软件时将它设为默认首页,还好现在不怎么用 IE)。
    # m9 {- c+ E" p: ?3 ?6 J点击百度产品的登录,一般会跳转到 passport.baidu.com,在这个页面完成登录,也有些是浮层,但登录实现方式一样:
    2 i$ g% j( \7 x3 b1.填写完用户名密码后,点击“登录”按钮。, R2 }" `, `. }, I4 t; l& l
    2.js 创建一个 div 容器,在这个容器中主要创建两个元素:form 表单和 iframe。
    3 t( ~8 x2 u$ @' T+ C, `+ L1.from 中包含很多 type="hidden" 的 <input/> 标记,主要包含填写内容和其他相关内容,如要登录的产品标识和成功后的跳转地址等。form 的提交目标窗口指向之后的 iframe。8 f# J# P! L8 D+ R6 i4 r. M8 m/ M% e$ `
    2.iframe 初始地址所一个 _blank.html 文件,会造成一次 http 请求。
    ; ~  n) \/ x, J3.这些内容都是拼成一个字符串,一次性写入的。' G% N; Q3 _" j" ^! {2 z
    3.动态创建节点完成后,马上提交数据,指向 iframe 中 passport.baidu.com/v2/api/?login。: Z) e1 z* \4 z& n2 `
    4.提交返回的结果内容在 iframe 中,通过 js 中的 'location.replace()' 跳转 iframe 到一个新的页面,这个页面是第2步中的表单项 'staticpage' 指定的,一般都叫 v3Jump.hmtl,不同产品只是路径不同。
    9 ~& ]9 z4 K' M' B# l5.v3Jump.html 中的 js 的作用就是以形如 parent.someMethod({}) 的方式调用 iframe 父级窗口的 js 方法。涉及到不同域名调用主窗口 js 方法,因此一般 v3Jump.html 都是放在和主窗口同一域名下。" ?. p2 z/ L2 }1 s7 x2 Y4 n5 B/ ~. f/ C3 s
    6.主窗口的 js 处理页面表现,同时为了实现跨域,会调用 https://user.hao123.com/static/crossdomain.php?bdu=...&t=3434312,这个 php 会根据 bdu 值验证登录状态,并设置 hao123.com 这个域名的 cookie 登录标识。比较巧妙的是,百度把这个地址作为一个 Image 对象的 src 属性,这样能完成请求,还不会渲染到页面上。/ k4 u, p3 n* W* o. ]3 f& }1 m8 q/ M( f
    7.最后,主窗口的 js 跳转页面到指定的地址。
    : A. |0 y; y3 E9 [% t) k
    " Q* R: Q2 G; Y# K9 }' k5 _$ e新浪的 SSO+ ^; y" P4 B( d# b8 ~
    新浪的独立域名好像只有一个 weibo.com,其他产品都是在 sina.com.cn 下。它的登录方式与百度基本相同,这里挑选不同的几点说明。
    3 t: A2 ?/ A; |) s8 E在 weibo.com 登录
    8 y  ?$ u/ C( |% s1.同百度
    % y2 @+ a/ |2 U* D0 U( k! [1 I1 l3 W4 F! ]2.同百度; f0 T" X: a% s0 t6 g8 t
    3.提交数据到 iframe, 指向 login.sina.com.cn/sso/login.php,提交表单后,会立马删除 from 节点(百度只在登录失败再次提交时才替换这个 form 节点)
    2 {, q. a/ f( U8 ]+ |4.如果登录失败,iframe 中的内容为 location.replace() 跳转到 weibo.com/ajaxlogin.php;如果登录成功,则跳转地址为 weibo.com/sso/login.php,该文件返回 302,跳转到 ajaxlogin.php。5 W% Z" s8 b$ p; Z6 q$ v: g9 e/ K
    5.ajaxlogin.php 负责用形如 parent.someMethod({}) 方式调用父窗口 js,处理页面。1 V; ^1 ~  c& |
    6.父窗口 js 删除 iframe 节点
    8 C, H3 e2 k- _% n7.同百度
    0 W+ I  s& |/ K; M新浪其他 sina.com.cn 子域登录$ h8 J- ]' C1 b- O+ g; d1 S6 b4 Z
    1.同 weibo
    7 \7 W6 R8 g: X+ ]' e2 |! J9 S, j2.同 weibo
    ( I0 V! W& \7 g  Z3.同 weibo,但不会删除 form 节点
    9 h! ~& u, k- `0 j: E3 Z$ a4.这里有些不同,login.sina.com.cn 下,login.php 的内容用 location.replace() 指向 login.sina.com.cn/crossdomain2.php,由这个页面调用 parent.someMethod();而在新浪首页,login.php 中先设置 document.domain='sina.com.cn'(login.php 与页面域名不完全相同),然后再调用 parent.someMethod()。
    " f) }0 b6 g/ \7 x- [' W, t5.父窗口的 js 处理页面表现,并用jsonp方式(放到script标记的src中)调用 weibo.com/sso/login.php 来完成跨域登录。5 ]$ Y4 P! c: R! s
    6.结束
    # Y  ]/ Z: c# l- p8 Q新浪的登录 js 并不统一,明显 weibo 的 js 处理的更精细。
    & t" R& {4 u# `8 d0 }weibo 登录中的第 4 步,iframe 中跳转方式实现对跨域的访问,显然有些局限。如果还有其他独立域名需要访问,这种跳转将无法兼顾。
    : b# n4 \. M5 t8 ~总结
    7 V5 O# [* u5 O3 C" M5 }8 C; U上面两个站点的实现方式基本相同,都是用 iframe 登录,然后在 iframe 中跳转来达到通过同一入口进行登录。难点在于跨域,特别需要注意的是:2 i5 B3 P5 T; ]: d! s) }7 G
    •iframe 中的 js 如果要访问父窗口的方法,需要保证域名相同,或者主域相同并都设置domain属性为主域地址,否则浏览器会报安全警告。
    % k, K. y% ^; w" B$ M1 U; f•跨域只要发起跨域的http请求即可,可以放到 script 标记的src中,也可已放到图片对象的 src 中,推荐后者,因为后者不用放到dom节点中。需要注意的是,这两种方式都要带一个每次都不同的参数,可以是时间戳,以防止浏览器的自动缓存。# @, P( Y- r, s* e
    上面着重关注了访问的跳转顺序,还有一个关键点是如何标识登录状态。上面的方案中,都会在请求跨域文件时,带上登录返回的一个唯一字符串,将它作为一个 token,在后端验证登录,识别登录的用户。可以把这个 token 设置为很短的时间有效,如1分钟,并在访问一次后删除,可以保证一定的安全性,但是如果在使用前截取,那么可以拿到任何一个地方登录。因为上面两个网站对跨域文件的访问都是写在主窗口的js里,因此可以很容易设置断点获取之。
    ! @' {. q7 ]/ P7 w据说 Google 在这点上是安全的,可惜身边没法翻墙,留待以后吧。
    # R' Y% T( b* \& N- T) _8 s- P8 i* H$ X; B
    补记" _& o5 ]; q' ?. s% a7 s! G, ~
    *2013-8-4
    , t. h: d9 \2 h& K( }& @周末有空折腾了一下翻墙,找到个超级好东西:SmartHosts,Youtube/Facebook/twitter... 都可以上了。; ?* s$ e( \) H/ W2 u5 C  ~
    Google SSO 实现方式
    0 _8 y! o% R& OGoogle 所有产品的登录都是通过 https://accounts.google.com/ 进行处理,基本流程如下:
    1 V" n) t4 [9 X+ m1.在 Google 产品站点击“登录”,会跳转到 https://accounts.google.com/ServiceLogin 登录;
    3 v# V; g) u( q" E. @- _* t2.表单 post 提交到 https://accounts.google.com/ServiceLoginAuth 验证;
    , f* K! r( `7 T% R) b. b. ^( M# A: Z3.登录成功则直接通过 302 转到 https://accounts.google.com/CheckCookie,访问跨域产品的页面,一般是 accounts.hostname/accounts/SetSID,设置登录cookie;( {2 {+ l2 v/ |8 b7 R/ z9 X
    4.页面跳转回登录来源页。2 Y' R0 D9 e' f6 f3 w
    针对不同的来源,具体处理上在第3步有些差别:8 |' P+ R# {0 Y" ]8 f' i2 E/ a. ^
    •如果登录来源是 *.google.com 或 youtube.com,则直接通过302指向 accounts.youtube.com/accounts/SetSID,之后该地址再转向到来源地址。
    ! O  H5 z0 j# M) z5 A" ~$ v( p9 H•如果登录来源是 *.google.com.hk,则返回200,通过 jsonp 请求 accounts.google.com.hk/accounts/SetSID 和 accounts.youtube.com/accounts/SetSID
    : q  Q" x4 c! N7 }5 j- E可以看到,基本原理是一样的,都是登录后,访问一下跨域的页面,完成登录信息的cookie设置。0 L( \2 a# K" k
    过程中通过修改 accounts.youtube.com 的 ip 指向,截取到了登录后的 /accounts/SetSID 链接,直接在一个新的浏览器中访问,是可以完成登录的。因此,Google 的 token 也不能保证这种截取的安全性。# |1 _7 t. t, n
    原文转自:http://calefy.org/2013/07/31/how-to-achieve-sso-login.html8 U. X, r% c" C$ ?
    , I5 h9 X# L; Q0 O2 c

    科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、科帮网管理员和版主有权不事先通知发贴者而删除本文


    JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

    快速回复
    您需要登录后才可以回帖 登录 | 立即注册

       

    关闭

    站长推荐上一条 /1 下一条

    发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
    快速回复 返回顶部 返回列表