Session 如何跨多个域创建共享登录服务?

Session 如何跨多个域创建共享登录服务?,session,cookies,login,shared,autologin,Session,Cookies,Login,Shared,Autologin,我对如何实现共享跨域登录系统以及要采取的最佳实践和安全预防措施感兴趣。如果您熟悉37Signals,您可能已经习惯于使用共享的通用身份验证机制,这样,如果您使用不同产品的顶级导航,您就不必随后登录。我想以类似的方式实现一些东西 我在网上找到的最接近的东西是维基百科上的条目和对的回复,在本例中可能略有不同 我已经检查了他们的会话cookie,以了解他们在此过程中正在做什么。最初,每个产品链接都有一个“goto”按钮,即: 使用FireCookie和Firebug中的NET选项卡,我能够看到设置的

我对如何实现共享跨域登录系统以及要采取的最佳实践和安全预防措施感兴趣。如果您熟悉37Signals,您可能已经习惯于使用共享的通用身份验证机制,这样,如果您使用不同产品的顶级导航,您就不必随后登录。我想以类似的方式实现一些东西

我在网上找到的最接近的东西是维基百科上的条目和对的回复,在本例中可能略有不同

我已经检查了他们的会话cookie,以了解他们在此过程中正在做什么。最初,每个产品链接都有一个“goto”按钮,即:

使用FireCookie和Firebug中的NET选项卡,我能够看到设置的Cookie以及过程中发生的重定向。
goto
url触发302重定向到:

将重新创建会话标识符,很可能是出于CSRF目的。Cookie中的一些数据以及GET参数sig使用base64_decode部分解密为以下内容:

// sig GET param
array(2) {
  [0]=>
���ף�:@marshal_with_utc_coercionT7�z��<k��kW"
  [1]=>
  string(18) "���k�<kn8�f���to��"
}

// _basecamp_session cookie session param
string(247) {
:_csrf_token"1Sj5D6jCwJKIxkZ6oroy7o/mYUqr4R5Ca34cOPNigqkw=:session_id"%060c0804a5d06dafd1c5b3349815d863"
flashIC:'ActionController::Flash::FlashHash{:
@used{: auth{"
              MY_COMPANY{:
                       user_idi�3
:identity_idi�W����������s�]��:�N[��:
//sig GET param
阵列(2){
[0]=>

���ף�:@使用utc强制7封送�Z�� 你有没有试过嗅嗅一下来回发送的东西?它可能会帮你进一步分解东西


正如所提到的,也许使用OAuth/OpenID对您来说是一个前进的方向?

我认为Q中的关键是您在哪里写“如果您使用不同产品的顶级导航,您不必随后登录”

我会解释: 您希望能够从site1.com移动到site2.com,并让site2.com知道您是通过site1.com登录的用户

因为Cookie不能在不同的域(子域除外,但我猜你不是在谈论子域)之间共享,所以你必须在site2.com的链接上传递一些信息,让它与后端对话,并知道你是什么用户

让我们从一个简单的解决方案开始,然后以我们的方式解决它带来的一些问题: 假设您在某个后端数据库上有一个users表,并且您的用户有一些ID。 现在假设用户在site1.com上进行了身份验证,他是数据库中的用户123。 最简单的解决方案是调用site2.com/url/whatever?myRealID=123 让site2检查此ID,并“相信”用户这确实是他

问题:任何看到你链接的人(甚至是你网站的有效用户)都可以创建myRealID=123的链接,或者尝试其他值。site2.com将接受他作为该用户

解决方案:假设您向用户表中添加了一个唯一的GUID,并且如果用户123的GUID为8dc70780-15e5-11e0-ac64-0800200c9a66,则不要使用可猜测的ID,然后调用site2.com/url/whatever?myGuid=8dc70780-15e5-11e0-ac64-0800200c9a66

新问题:即使很难有人猜到你的用户的GUID,但他的GUID仍可能被看到此链接的中间人劫持,有人将获得GUID,他可以永远使用它

解决方案:使用保存在服务器上的私钥对字符串进行签名,该字符串包含以下数据项、当前时间戳、目标站点(即“site2.com”)所述GUID,此签名可以转换为“这证明此链接是由站点在所述时间为具有此GUID的用户创建的,并由此域验证“并将其连同时间戳和GUID一起发送到site2.com。现在,当site2.com获得链接时,他可以确保该链接已正确签名,并且如果某个中间人或原始用户试图以任何方式更改该链接(我修改时间或GUID),则签名将不匹配,site2.com将拒绝对该用户进行身份验证

最后一个问题:如果链接被中间人截获,他仍然可以使用其他机器的if

解决方案:向传递的参数中添加一个nonce。nonce只是一个随机数,您的身份验证系统应确保它不允许您使用该数字进行多次身份验证(因此命名为N(number)-一次)。请注意,这意味着您在site1.com上创建的每个指向site2.com的链接都应该有一个不同的nonce,需要将其保存在后端以供以后验证

因为您不想一直将记录添加到此nonce表中,所以可以自定义此链接仅在创建后的某个给定时间内有效。因此,您可以创建早于此时间限制的nonce记录

我希望这是你在哪里寻找的大纲。 我可能遗漏了一些东西,但这些是基本准则,使用签名来证明链接中数据的真实性,并使用nonce来防止中间人攻击。如果可能,我还建议对这些链接使用HTTPS


Eyal

看看Jasig CAS。我认为它会做你想做的事。它是开源的,有许多插件允许你使用多个认证源和多个域/语言进行认证。

允许用户选择使用他们的facebook/yahoo/gmail/openID解决方案是一个开始,但这并不是一个开始巧妙地解决实施或使用自己的解决方案的问题

在过去开发和管理了一个实现(我们最终选择了SiteMinder,但我猜你不想要一个真正产品的成本),我认为Eyal有一个非常好的想法,但我想对它做一些调整

在进行身份验证时,生成一个随机代码(可以是GUID值,但不是每个用户的静态代码),该代码与用户id一起存储在事务表中。此代码具有最长的生存期(您需要判断该时间段的安全值)。理想情况下,此代码可以使用用户名哈希或加密