我在不同领域的几个网站:example.com
,example.org
,mail.example.com
和passport.example.org
.所有网站都具有共同的外观,应该共享相同的用户群.
在这种极端情况下,我仍然希望所有站点透明地(尽可能地)共享具有以下关键属性的用户会话:
单点登录.当用户passport.example.org
登录并访问任何其他站点时 - 他应该被视为已登录.
登录用户$username
在站点标题和不同的导航菜单中获得"Hello ",问候语,列出他们有权访问的服务.如果他没有登录,而不是打招呼有一个"登录"链接,指向passport.example.org/signon
.
可信域列表是已知的,因此使用OpenID或某些homebrewn轻量级协议实现起来相当简单.当用户第一次访问该站点时,我将其重定向到特殊身份验证端点passport.example.org
,然后以静默方式将其重定向回来,其中包含身份信息(或"未签名"匿名身份).对于大多数浏览器,这是完全透明的 显然,我正在使用nonce值来对抗重定向循环.
单一签收.当用户下次访问任何网站时点击任何网站标题中的"注销"时,他应被视为"未登录".
OpenID不是为此而设计的.我当前的想法(我已经有一个部分工作的实现)是在DB中发送不是用户身份,而是"全局"会话令牌和共享全局会话表(global_session_token↔用户关系).
机器人和无cookie用户支持.站点具有公共区域,用户代理可以访问这些区域而无需任何cookie支持.
因此,我在(1)中提到的重定向成为一个问题,因为对于每个单页请求,我最终都会将用户代理抛给auth端点并返回.这不仅会使机器人感到困惑,而且会很快污染我的会话数据库.我绝对不想显示"嘿,你没有启用cookie,走开!"页面,这是非常粗鲁和令人失望的.虽然我需要cookie支持登录,但我希望用户可以自由阅读网站的内容等等 - 没有任何限制.
而且我明确地不希望把URL中的会话ID,除了我刚才提到了一些透明的跨域重定向.我认为这样做是一个安全问题,通常只是一件坏事.
在这里,我几乎没有想法.
好吧,我知道这很难,但谷歌实际上(这是否在某种程度上google.com
,
google.
很多-的-通用顶级域名,gmail.com
等等),对不对?所以这应该是可能的.
我要感谢协议描述的想法(这是最好的)或系统的链接(要么是代码阅读,要么是直播现场观看和学习)已经成功地实现了这样的事情.
总结一下:几个域没有共同的根,共享用户群,单点登录,单点注销,匿名浏览不需要cookie.
所有站点都在同一个网络上(但在不同的服务器上)并且部分共享同一个PostgreSQL数据库(在同一个数据库的不同方案中).大多数站点都是用Python/Django编写的,但其中一些是使用PHP和Ruby on Rails.虽然我正在考虑与框架和语言无关的东西,但我很感激指向任何实现.即使我不能使用它们,如果我能理解它是如何完成的,那么也许我能够实现类似的东西.
那么,让我再解释一下.(所有网址都是虚构的!)正如我所说,访问者访问http://www.yourwebpage.com并表示他想登录.他被重定向到http://your.loginpage.org?return=http: //www.yourwebpage.com/Authenticated他必须提供他的用户名和密码.
当他的帐户信息有效时,他将返回登录URL中提供的页面,但附加一个将用作ID的参数.因此,他访问http://www.yourwebpage.com/Authenticated?ID=SharedSecret,其中SharedSecret将是一个临时ID,有效期为30秒或更短.
当您的身份验证页面被调用时,该页面将调用yourwebpage.com和loginpage.org之间共享的方法,以查找SharedSecret的帐户信息以检索更永久的ID.此永久ID存储在yourwebpage.com的网络会话中,不应向用户显示.
共享方法可以是任何东西.如果两台服务器都在同一台机器上,则它们都可以访问同一个数据库.否则,他们可能会通过Web服务与另一台服务器通信.这将是服务器到服务器的通信,因此无论用户是机器人还是没有cookie支持都无关紧要.用户不会注意到这部分.
您唯一需要处理的是用户的会话.通常,将向用户发送存储在cookie中的会话ID,但它也可以作为GET请求的一部分作为URL的一部分.但是,通过向表单添加隐藏的输入字段,在POST请求中使用会话ID会更安全一些.
幸运的是,一些Web开发语言已经提供了会话支持,因此您甚至不必担心维护会话和发送会话ID.不过,这项技术很有意思.您需要注意,会话应始终是临时的,因为会话ID被劫持的风险.
如果您必须处理不同域上的多个站点,那么您将需要首先进行一些服务器到服务器的通信.最简单的方法是让他们共享同一个数据库,但最好围绕这个数据库构建一个Web服务,以获得额外的保护.确保此Web服务仅接受来自您自己域的请求,以便添加更多保护.
当您具有服务器到服务器的连接时,用户将能够在您的域之间切换,只要您将会话ID传递到新域,用户就会登录.如果用户正在使用cookie,会话丢失的可能性很小,需要再次登录.如果没有cookie,如果会话ID在浏览页面之间丢失,则用户可能必须再次登录才能获得新的cookie.(例如,参观者前往参观谷歌,然后返回到你的网站.用一个cookie,会话可以从cookie中读取.没有Cookie,因为谷歌的会话丢失,将无法通过会话ID转发.
做请记住,在不同域之间传递会话ID是一种安全风险.会话ID可能被劫持,从而使其他人可以模拟您的访问者.因此,会话ID应该是短暂的和混淆的.但即使一个黑客获得对会话ID的访问权限,他仍然无法完全访问该帐户本身.他将无法拦截服务器到服务器的通信,因此他无法使用您的用户信息访问数据库,除非他直接进入登录页面.
AFAIK,Google只为"Google.com"域名使用Cookie.但谷歌也使用OpenID,它允许通用的登录机制.基本上,这可以通过将您重定向到一个特殊的登录页面来实现.此登录页面将检测您是否已登录,如果您未登录,则会要求您登录.否则,它会直接重定向到下一页.
因此,在您的情况下,用户将打开somepage.example.com,此应用的会话没有登录ID.因此,它会将用户重定向到用户将登录的logon.example.biz.此页面后面也将是一个会话,该会话将告诉用户已经登录.(或者不是,在这种情况下,用户必须首先登录.)然后重定向用户somepage.example.com?sessionid=something这个sessionid将存储在somepage.example.com的会话中.然后,此会话还将知道用户已登录,并且对于用户来说,它几乎看起来是透明的.
实际上,用户被重定向两次.