JSP .NET PHP SSO

时间:2012-05-11 11:07:39

标签: php asp.net jsp cookies single-sign-on

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

3 个答案:

答案 0 :(得分:1)

简短回答:是的。

更长的答案:

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

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


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

你有两台服务器,我打电话给" A"和" B"。

" A"持有身份验证/登录系统," B"是您登录" A"。

时要登录的服务器

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

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

服务器" A"

会发生什么

" A"提供一个页面并给出一个会话" X",存储" Y"在饼干里。

无论用户使用什么服务器,都应该将用户发送到" A"登录这可以通过在每个页面上都有一个登录表单来实现,即#34;发布"对于" A",您会弹出一个弹出窗口,弹出由" A"提供的登录表单,或者您重定向到由" A"提供的页面。 (最后两个是Facebook如何做到的。)

" A"在关联会话中签署用户" X"与登录用户。

当用户访问服务器" A"给出的页面时,所有内容都是花花公子,因为它可以读取cookie" X"并知道发生了什么。因此问题是服务器" B" (或" C"或" D"等 - 这可以扩展)。

服务器" B"

会发生什么

当用户从服务器" B"访问某个页面时,您无法从" A"中读取该Cookie。所以有一个简单的选项,一个复杂的选项

简单:来自服务器" A"创建的页面的每个链接到服务器" B"将SessionID作为参数添加。服务器" B"然后谈谈服务器" A"获取会话详细信息。如果用户总是从服务器" A"到服务器" B"并且没有直接到达服务器" B" (例如通过谷歌等)。实际上,这不是一个很好的选择。

复杂:这是一系列事件。

  • 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"不会链接" X"和" Y"直到iFrame与之通信,所以当服务器" B"问服务器" A"你知道" Y",答案是“不”#);所以你需要监控服务器" A" ;让服务器" B"知道它已经登录了。您可以通过以下几种方式实现此目的:

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

    • 你可以重复这个' Server" B"联系服务器" A"'欺骗每个由" B' (这是你的应用程序连接到Facebook的方式,每次加载Facebook都会调用facebook)。但这确实会给您自己的服务器带来压力。

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

    • 您还可以使用"服务器到服务器"呼叫共享活动(例如"用户与" X"已获得和成就,更新您的本地缓存'或'用户与" Y"已经退出 - 记录" X" out')。我还通过Javascript调用备份这个,所以如果我在两个标签中查看两个页面,一个在服务器上,#34; A"

并且一次从服务器" B",如果我退出一个,那么Javascript调用将定期检查并将我从另一个中注销。

那么,安全吗?

" X"和" Y"都是公共字符串。这意味着,如果你偷了" Y"然后你可以伪装成" X"。实际上,这与窃取普通会话密钥" X"没有区别,但您可以采取更多措施来防止欺骗。您知道iFrame呼叫" A"应该来自完全相同的IP,用户代理和推荐人[注2],并且iFrame呼叫应该与来自" B"的请求同时出现。 (给予或接受网络延迟,允许30秒)。如果其中任何一个不匹配,则沟渠会话" Y",创建一个新会话" Y"并开始会议" Y"与" X"相同一遍又一遍。

下一步?

您可以执行此操作的许多变体,您可能需要进行调整以获得所需的确切流量。您也可以使用相同的系统登录多个应用程序(例如,我有Wordpress,SMF和自定义游戏共享数据,所以你登录一个,它注销另一个,即使应用程序在不同的服务器上 - 但他们共享一个域名,这样就可以共享cookie,这样可以更容易一些,但是他们不会分享会话,所以我已经诉诸于此。但作为最终用户,除了"重定向页面"或暂时的"你没有登录"当它们存在时,它们不应该注意到。

另一个变体是Server" A"还可以加载一个隐藏的iFrame来加载服务器上的页面" B"。同样的沟通,恰恰相反。由于用户无法访问" A",iFrame将链接" X"和" Y"在用户登录之前 - 它是不可避免的。因此,当用户从服务器访问页面时," B"," X"和" Y"链接,我们立即知道他们是否登录。但是,您仍然需要轮询,因此它并不容易。

备注:

注1:使用javascript选项时,请小心。我写的一个系统太忙了,服务器无法应对(这个系统分布在5台服务器上)。 JavaScript没有得到响应,但继续尝试,这增加了负载。这意味着服务器与服务器之间的通信无法通过,并且很快就会使整个系统崩溃,因为所有的Apache套接字都被使用了。 Javascript继续进行轮询和轮询,即使在系统关闭后,浏览器仍在继续(当然)。我们不得不对旧的呼叫URL进行黑洞检查,更新呼叫以响应不同的URL,并以某种方式让所有用户“访问”。浏览器获取新的Javascript以便它们可以运行。因此,如果您选择轮询路线,请计划此方案。

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

注3:这是单点登录解决方案的建议,其中的变体已在多个站点上实施。我不是在寻找关于每种方法的各种优点,断断续续的负载,陷阱或潜在的安全漏洞等的辩论。它们供你在实施时思考。你一路上会发现一些陷阱。

答案 1 :(得分:0)

是的,如果3个网站位于同一个域中,则可能。如果不是,那么网站1创建的cookie将不会被发送到网站2。

答案 2 :(得分:0)

我最近发布了一款名为“单点登录服务器/客户端”的新产品:

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

现在只有一个PHP服务器和客户端。如果您对使用它感兴趣,最有必要在PHP主机上安装服务器部分。然后需要一些移植工作来获得ASP.NET和JSP的工作客户端。但它确实跨域工作。我应警告您,目前,每个客户端实例都需要再次登录。