我对如何实现共享跨域登录系统以及最佳实践和安全预防措施感兴趣。如果您熟悉 37Signals,您可能习惯于他们使用共享的通用身份验证机制,如果您使用顶级导航到不同的产品,则无需随后登录。我想以类似的方式实现一些东西。
我在网上找到的最接近的东西是维基百科上的条目 Central Authentication Service以及对Cross Domain Login - How to login a user automatically when transfered from one domain to another的响应,在本例中可能略有不同。
我检查了他们的 session cookie,以了解他们在此过程中所做的事情。最初,每个产品链接都有一个“goto”uristub,即:
https://MY_COMPANY.campfirenow.com/id/users/[int_identifier]/goto
使用 FireCookie 和 Firebug 中的 NET 选项卡,我可以看到设置的 cookie 以及进程中发生的重定向。 goto
url 触发 302 重定向到:
https://MY_COMPANY.basecamphq.com/login/authenticate?sig=[BASE64_ENCODED_AND_ENCRYPTED_DATA]
重新创建 session 标识符,很可能是出于 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[��:
“”
编码破坏了代码块。感谢您的帮助!
最佳答案
我认为你的问题中的关键是你写的“如果你使用顶级导航到不同的产品,你就不必随后登录”。
我来解释一下: 您希望能够从 site1.com 移动到 site2.com,并让 site2.com 知道您是通过 site1.com 登录的用户。
因为 cookie 不能在不同域之间共享(子域除外,但我猜您不是在谈论子域),您必须在指向 site2.com 的链接上传递一些信息,以使其与其后端对话并知道您是什么用户。
让我们从一个简单的解决方案开始,然后努力解决它带来的一些问题: 假设您在某个后端数据库上有一个用户表,并且您的用户有一些 ID。 现在假设用户在 site1.com 上进行了身份验证,并且他是数据库中的用户 123。 最简单的解决方案是调用 site2.com/url/whatever?myRealID=123 并让 site2 检查此 ID 并“相信”用户这确实是他。
问题:看到您的链接的任何人(甚至是您网站的有效用户)都可以使用 myRealID=123 创建链接或尝试使用其他值。并且 site2.com 将接受他作为该用户。
解决方案:不要使用可猜测的 ID 假设您向用户表添加了一个唯一的 GUID,并且如果用户 123 的 guid 为 8dc70780-15e5-11e0-ac64-0800200c9a66,则调用 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 不匹配。 com 将拒绝验证用户身份。
最后一个问题:如果链接被中间人拦截,他仍然可以从其他机器使用该链接。
解决方案:在传递的参数中添加nonce。随机数只是一个随机数,您的身份验证系统应确保它不允许您多次使用该数字进行身份验证(因此命名为 N(number)-ONCE)。请注意,这意味着您在 site1.com 上创建的每个指向 site2.com 的链接都应该有一个不同的随机数,需要将其保存在后端以供以后验证。
因为您不想永远向此随机数表添加记录,所以习惯上决定这样的链接仅在创建后的某个给定时间内有效。因此您可以创建早于该时间限制的随机数记录。
我希望这是您正在寻找的大纲。 我可能错过了一些东西,但这些是基本准则,使用签名来证明链接中数据的真实性,并使用随机数来防止中间人攻击。如果可能的话,我还建议对这些链接使用 HTTPS。
埃亚尔
关于session - 如何创建跨多个域的共享登录服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4306728/