0

我有以下情况: Website1 - php Website2 - ASP.Net Website3 - jsp 我需要实现单点登录,因为网站相互依赖。有没有办法创建一个可以在身份验证请求中获取的 cookie?因此,当用户在其中一个网站上登录时,我们会存储一个 cookie,该 cookie 可以被其他两个网站读取和解密,以便在重定向后处于登录状态?我使用相同的数据库和相同的表“shared.Users”来存储用户凭据。这里有什么帮助吗?谢谢

4

3 回答 3

1

简短的回答:是的。

更长的答案:

a) 如果服务器在同一个域(可以是不同的子域,但必须是同一个根域),那么它们都可以读取相同的 cookie。登录服务器使用会话 ID 创建一个 cookie,第二个网站的访问者读取 cookie 并传递给服务器,服务器对登录服务器进行后端调用以获取会话/用户详细信息并登录用户。

b) 如果服务器位于不同的域中,那么您有两种选择。一种是将会话 ID 作为字符串传递给第二台服务器(丑陋)。但更好(也更复杂)的是一系列隐藏帧。(您需要在 IE 中使用 P3P 才能工作 - 其他浏览器都可以)。基本上隐藏帧从登录域加载,并且可以读取/操作以获取会话 ID。这有点杂耍,但当你把它映射出来时效果很好。


编辑:单点登录选项(详细)

你有两台服务器,我称之为“A”和“B”。

“A”保存身份验证/登录系统,“B”是您登录“A”时要登录的服务器。

如果两个服务器提供完全独立的页面,或者一个是另一个内部的 iFrame,这将起作用。也将在不同平台上工作

首先要注意:服务器“A”需要与服务器“B”共享信息。有两种方法可以做到这一点,具体取决于您的情况。第一种选择是它们共享同一个数据库并在其中存储数据,另一种是服务器相互“对话”:如果您使用后者,请使用 CURL 并添加校验和并向 HTTP 调用添加特定标头- 这应该使它足够安全(只要没有人看到代码)。如果两者不在同一个数据中心,您还应该在两者之间添加 SSL 通信——但用户将永远不会看到这些调用。我推测您不会共享数据库(不同平台),因此您需要允许服务器一起交谈。

服务器“A”上发生了什么

“A”提供一个页面并提供一个会话“X”,将“Y”存储在 cookie 中。

无论用户在哪个服务器上,都应该将用户发送到“A”进行登录。这可以通过在每个“发布”到“A”的页面上设置一个登录表单来完成,您可以执行一个弹出窗口来弹出“A”提供的登录表单,或者您重定向到“A”提供的页面。(最后两个是 Facebook 的做法。)

“A”在将会话“X”与登录用户相关联中签署用户。

当用户访问服务器“A”提供的页面时,一切都很好,因为它可以读取 cookie“X”并知道发生了什么。因此问题是服务器“B”(或“C”或“D”等 - 这可以扩展)。

服务器“B”上发生了什么

当用户从服务器“B”访问页面时,您无法从“A”读取 cookie。所以有一个简单的选项和一个复杂的选项

简单:从服务器“A”创建的页面到服务器“B”的每个链接都将添加 SessionID 作为参数。服务器“B”然后与服务器“A”对话以获取会话详细信息。如果用户总是从服务器“A”到服务器“B”而不是直接到达服务器“B”(例如通过 Google 等),这很好。实际上,这不是一个很好的选择。

复杂:这是事件的顺序。

  • B 将会话“Y”分配给用户并将其存储在 cookie 中。

  • B 提供了一个包含“隐藏”iFrame 的网页。隐藏 iFrame 的 src 将是由“A”传递的页面,并且您将会话“Y”作为 GET 参数附加到调用中。

  • iFrame 可以访问会话“X”(通过 cookie)和会话“Y”(通过 GET 参数)。

  • (慢慢阅读:) iFrame 告诉服务器“A”,如果您从服务器“B”听到用户有会话“Y”,则向“B”提供与会话“X”相同的凭据 - 即会话“Y”与“X”相同,将两者联系在一起。

  • (现在是棘手的部分)一旦建立链接,服务器“B”然后需要联系服务器“A”并说“我是会话“Y”,这个人是

已登录?'。服务器“A”会将“X”匹配到“Y”并说“是的,这是用户的详细信息。”

当然,事情没那么简单……:

这种方法的问题是“B”提供的第一个页面会假设用户没有登录。(服务器“A”在 iFrame 与它通信之前不会链接“X”和“Y”,所以当服务器“B”询问服务器“A”你知道“Y”时,答案将是“不”。 ) 所以你需要监视服务器“A”,让服务器“B”知道它已登录。您可以通过多种方式执行此操作:

  • 如果服务器“B”从未发送过带有 cookie 的页面(即会话“Y”是新的),或者服务器“B”查询服务器“A”并且服务器“A”响应它从未听说过会话“Y”,然后提供一个带有隐藏 iFrame 的空白“重定向页面”,在短时间内,再次尝试服务器“A”应该知道“Y”是谁,并且可以确认他是否已登录。作为替代方案,您提供整个页面(未登录)并让 JavaScript 不断调用服务器“B”以查看服务器“A”现在是否知道“Y”是谁,以及当您刷新以登录用户时得到回应。[注1]

    • 您可以重复此“服务器“B”联系人服务器“A””欺骗由“B”传递的每个页面(这是您的应用程序连接到 Facebook 的方式,每个页面加载时都会调用 facebook)。这确实会给您的自己的服务器,虽然。

    • 或者,您可以独立跟踪服务器“B”上的会话“Y”并假设用户已登录,直到服务器“A”与您联系以说出与会话“X”相关联的用户(因此与会话“Y”相关联) ) 已注销 - 然后您也将用户从会话“Y”中注销。

    • 您还可以使用“服务器到服务器”调用共享活动(例如,“与“X”关联的用户已获得成就,更新您的本地缓存”,或“与“Y”关联的用户已注销 - 将“X”注销还')。我还通过 Javascript 调用支持这个,所以如果我在两个选项卡中查看两个页面,一个来自服务器“A”

并且一旦从服务器“B”中注销,如果我从其中一个注销,则 Javascript 调用将定期检查并将我从另一个注销。

那么,安全吗?

“X”和“Y”都是公共字符串。这意味着如果您窃取“Y”,那么您可以伪装成“X”。实际上,这与窃取普通会话密钥“X”没有什么不同,但您可以采取更多措施来防止欺骗。您知道对“A”的 iFrame 调用应该来自完全相同的 IP、用户代理和引用者 [注 2],并且 iFrame 调用应该与来自“B”的请求同时出现(给予或接受网络延迟,允许 30 秒)。如果其中任何一个不匹配,则放弃会话“Y”,创建一个新会话“Y”并重新开始“会话“Y”与“X”相同的过程。

下一步去哪儿?

你可以做很多变化,你可能需要调整以获得你需要的确切流量。您还可以使用同一系统登录多个应用程序(例如,我有 Wordpress、SMF 和一个自定义游戏,它们都共享数据,因此您登录一个并在另一个上注销,即使应用程序位于不同的服务器上 - 但它们共享一个域,因此可以共享 cookie,这会更容易一些,但它们不共享会话,所以我使用了这个)。但是作为最终用户,除了“重定向页面”或暂时的“您没有登录”之外,他们不应该注意到。

另一种变体是服务器“A”还可以加载隐藏的 iFrame,该 iFrame 在服务器“B”上加载页面。相同的交流方式,只是相反。由于用户在不访问“A”的情况下无法登录,因此 iFrame 在用户登录之前将链接“X”和“Y”——这是不可避免的。因此,当用户从服务器“B”访问页面时,“X”和“Y”是链接的,我们立即知道他们是否登录。但是,您仍然需要轮询,因此它并不容易。

笔记:

注意 1:使用 javascript 选项时,请小心。我写的一个系统太忙了,服务器无法处理(这分布在 5 个服务器上)。javascript 没有得到响应,但继续尝试,这增加了负载。这意味着服务器->服务器通信也无法通过,并且由于使用了所有 Apache 套接字,它很快使整个系统崩溃。Javascript 不断地轮询和轮询,即使在系统关闭之后,浏览器也会继续运行(当然)。我们必须黑化旧的调用 URL,更新调用以响应不同的 URL,并以某种方式让所有用户的浏览器获取新的 Javascript,以便它们能够正常工作。因此,如果您选择投票路线,请为这种情况做好计划。

注意 2:通常您不应该完全依赖这些来验证用户,因为它们很容易被更改/欺骗。但在这种情况下,它们应该完全相同,并且非常适合确认用户没有尝试做一些有趣的事情。

注意 3:这是单点登录解决方案的建议,其变体已在多个站点上实施。请不要就每种方法的各种优点、服务器负载、陷阱或潜在的安全漏洞等进行辩论。它们供您在实施时考虑。在此过程中,您会发现一些陷阱。

于 2012-05-11T11:17:19.710 回答
0

是的,这是可能的,前提是这 3 个网站在同一个域中。如果不是,则网站 1 创建的 cookie 将不会发送到网站 2。

于 2012-05-11T11:15:12.567 回答
0

我最近发布了一个新产品,叫做单点登录服务器/客户端:

http://barebonescms.com/documentation/sso/

现在只有一个 PHP 服务器和客户端。如果您有兴趣使用它,在 PHP 主机上安装服务器部分是最有意义的。然后需要进行一些移植工作才能获得适用于 ASP.NET 和 JSP 的客户端。但它确实可以跨域工作。我应该警告您,目前,每个客户端实例都需要重新登录。

于 2012-05-12T08:13:29.630 回答