多个站点的透明用户会话(单点登录+单点登录)

时间:2009-06-25 10:22:12

标签: authentication session single-sign-on

我在不同的网域中有多个网站:example.comexample.orgmail.example.compassport.example.org。所有网站都具有共同的外观和感觉 应该共享相同的用户群。

在极端情况下,我仍然希望所有网站透明地(尽可能多) 使用以下关键属性共享用户会话:

  1. 单点登录。当用户在passport.example.org登录并访问时 任何其他网站 - 他应该被视为登录。

    登录用户在网站标题中获取“Hello,$username”问候语并且不同 导航菜单,列出他们有权访问的服务。如果他没有登录,而是 问候语中有一个“登录”链接,指向passport.example.org/signon

    可信域列表是已知的,因此实现起来也相当简单 使用OpenID或一些homebrewn轻量级协议。当用户第一次点击时 网站,我正在将他重定向到passport.example.org的特殊身份验证端点, 然后默默地将他重新定向回来,带有身份信息(或“未登录” 匿名身份)包括在内。对于大多数浏览器,这是完全透明的 显然,我正在使用nonce值来对抗重定向循环。

  2. 单点注销。当用户点击任何网站标题中的“注销”时 下次他访问任何网站时 - 他应该被视为“不登录”。

    OpenID不是为此而设计的。我目前的想法(我已经有了部分工作 实现)是发送不是用户身份,而是“全局”会话令牌和共享 DB中的全局会话表(global_session_token↔用户关系)。

  3. 机器人和无Cookie用户支持。网站有公共区域,应该 可由用户代理访问,无需任何cookie支持。

    因此,我在(1)中提到的重定向成为一个问题,因为 每一页请求,我最终都会将用户代理投入到auth端点并返回。 这不仅会使机器人感到困惑,而且会污染我的会话数据库 很快就死了。我绝对不想显示“嘿, 你没有启用cookie,就走开!“页面,那是非常粗鲁的 令人失望的。虽然我需要cookie支持登录,但我希望用户可以自由阅读 网站的用途等等 - 没有任何限制。

    我明确地想要将会话ID放在URL中,除了一些透明的 我提到的跨域重定向。我认为这样做是一个安全问题 而且通常只是一件坏事。

    在这里,我几乎没有想法。

  4. 好的,我知道这很难,但Google确实以某种方式(google.com执行此操作, google. 很多通用顶级域名gmail.com等等,对吧?所以这应该是 可能的。

    我要感谢协议描述的想法(那是最好的)或链接 系统(要么是代码阅读,要么就是现场观看和学习) 成功实现了这样的事情。

    总结一下:几个没有共同根域,共享用户群,单点登录,单点注销,匿名浏览无需cookie的域名。

    所有网站都在同一个网络上(但在不同的服务器上),部分网站 共享相同的PostgreSQL数据库(在同一数据库的不同方案中休息)。 大多数站点都是用Python / Django编写的,但其中一些是使用PHP和Ruby on Rails。虽然我正在考虑与框架和语言无关的东西,但我很感激指向任何实现。即使我无法使用它们,如果我能理解它是如何完成的,那么我也许能够实现类似的东西。

7 个答案:

答案 0 :(得分:31)

那么,让我再解释一下。 (所有网址都是虚构的!)正如我所说,访问者访问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的一部分。但是,通过在表单中​​添加隐藏的输入字段,将会话ID放在POST请求中会更安全一些。

幸运的是,一些Web开发语言已经提供了会话支持,因此您甚至不必担心维护会话和发送会话ID。不过,这项技术很有意思。您需要注意,会话应始终是临时的,因为会话ID被劫持的风险。

如果您必须处理不同域上的多个站点,那么您将需要首先进行一些服务器到服务器的通信。最简单的方法是让他们共享同一个数据库,但最好围绕这个数据库构建一个Web服务,以获得额外的保护。确保此Web服务仅接受来自您自己域的请求,以便添加更多保护 当您具有服务器到服务器的连接时,用户将能够在您的域之间切换,只要您将会话ID传递到新域,用户就会登录。如果用户正在使用cookie,会话丢失的可能性很小,需要再次登录。如果没有cookie,如果会话ID在浏览页面之间丢失,则用户可能必须再次登录才能获得新的cookie。 (例如,访问者访问Google,然后返回您的网站。使用Cookie,可以从Cookie中读取会话。如果没有Cookie,则会话会丢失,因为Google不会向前传递会话ID。<登记/>
请记住,在不同域之间传递会话ID存在安全风险。会话ID可能被劫持,从而使其他人可以冒充您的访问者。因此,会话ID应该是短暂的和混淆的。但即使黑客获得对会话ID的访问权限,他仍然无法完全访问该帐户本身。他将无法拦截服务器到服务器的通信,因此无法使用您的用户信息访问数据库,除非他直接进入登录页面。

答案 1 :(得分:5)

AFAIK,Google只为“Google.com”域名使用Cookie。但谷歌也使用OpenID,它允许通用的登录机制。基本上,这可以通过将您重定向到一个特殊的登录页面来实现。此登录页面将检测您是否已登录,如果您尚未登录,则会要求您登录。否则,它会直接将您重定向到下一页。

因此,在您的情况下,用户将打开somepage.example.com,此应用的会话没有登录ID。因此,它会将用户重定向到用户将登录的logon.example.biz。此页面后面也将是一个会话,该会话将告诉用户已经登录。(或者不是,在这种情况下,用户必须首先登录。)然后重定向用户somepage.example.com?sessionid=something这个sessionid将存储在somepage.example.com的会话中。然后,此会话还将知道用户已登录,对于用户来说,它几乎看起来是透明的。

实际上,用户被重定向两次。

答案 2 :(得分:1)

您使用的是ASP.NET吗?如果是这样,您可能需要查看enableCrossAppRedirects属性。

答案 3 :(得分:1)

如果您的所有应用程序都在一个域上,那么它并不太难,因为您可以使用域级cookie来处理会话控制。 (无Cookie会话管理很困难,但可以完成,但很难。)

但是,您在example.com域上指明了一些站点,在example.org域上指出了一些站点。

与我的google sigh-in和他们的orkut.com的其他网站玩一下,看起来当你点击需要凭据的页面时,它会将你重定向到一个公共站点进行帐户登录,然后重定向回来到原始站点,可能是在URL中传递某种会话令牌。据此,orkut.com服务器可能会直接与google.com服务器进行协商,以验证令牌并获取所需的任何其他用户信息。

有关域级Cookie的更多信息,需要

如果您有两个网站,例如foo.example.combar.example.com,,您可以设置特定于主机的Cookie,但您也可以为该网站设置一个cookie,域。

因此,foo.example.com可以专门为foo.example.com设置一个Cookie,它只会被自己看到,但它也可以为域example.com,和用户设置一个cookie转到bar.example.com他们也会看到第二个cookie。

但是,如果您还有一个网站snafu.example.org,,则无法看到foo设置的此域级Cookie,因为example.orgexample.com是两个完全不同的域。

您可以使用域级Cookie来维护同一域中站点之间的会话信息。

如何设置域级cookie取决于您的开发环境(我没有使用rails的经验,抱歉)。

答案 4 :(得分:1)

对于此解决方案,不需要护照服务器。

登入

  1. 登录
  2. 使用加密的会话ID和其他信息创建令牌
  3. 使用来自所有域的令牌显示img,以便在其上设置Cookie。
  4. Cookie授权

    1. 您已在所有域名中使用Cookie。
    2. 退出

      1. 清除Cookie
      2. 销毁会话
      3. 清除关系用户ID与DB中的最后一个会话ID(我认为您在用户表中保存会话ID以通过cookie上升会话)
      4. 我不能尝试这个解决方案。但是现在我和你(SSO)有同样的问题,明天我会尝试这个。

答案 5 :(得分:0)

对于SSO场景和联合身份,我使用过shibboleth,但我认为你需要更简单的解决方案,如上所述。

答案 6 :(得分:-4)

支持跨域功能的rails插件可以实现这一目标。

我想这样做,我想到的唯一方法就是强迫用户下载工具栏,或者一些能够自动处理登录的小空中应用程序。

我很想知道另一种方式'因为打击