使用 JSONP 和 cookie 进行跨域登录
Posted
技术标签:
【中文标题】使用 JSONP 和 cookie 进行跨域登录【英文标题】:Cross-domain login using JSONP and cookies 【发布时间】:2012-06-12 23:08:17 【问题描述】:我怎样才能让用户登录到一个域并自动登录到我的其他域,而无需他们在每个域上提交表单?
【问题讨论】:
【参考方案1】:我们都知道 cookie 不能跨域访问,因为这会带来安全风险。但是,使用一些技巧,有一些方法可以解决这个问题。基本上,我们在中心域上为用户设置 cookie,使用脚本检查该 cookie 的存在,然后使用 JSON-P 回调将该 cookie 复制到其他域。更详细:
登录
第 1 步
mydomain.com
(或myotherdomain.com
等)上显示的<form>
应发布到central.com/login
第 2 步
在central.com/login
上,用户名和密码得到验证,并在central.com
域上设置一个cookie,其中包含该用户的唯一值。然后用户被重定向回mydomain.com
SELECT unique_value FROM users WHERE username = $username
set cookie on central.com containing unique_value
第 3 步
回到mydomain.com
,我们嵌入了对central.com/check
的javascript调用。
<script type="text/javascript" src="http://central.com/check"></script>
第 4 步
在central.com/check
上,我们检查是否为用户设置了唯一cookie。然后我们嵌入一个 JavaScript 回调 (JSON-P),通知 mydomain.com
用户已登录。不包含敏感的用户数据,否则 hacker.com
可以嵌入此脚本并获取用户的信息。 (将适当的 Access-Control 标头设置为仅允许经过验证的域可以减轻这种风险。)相反,我们根据时间戳创建一次性哈希,以便mydomain.com
可以验证身份验证。
if cookie on central.com is valid
user_data = array(
'success' => true,
'uid' => $uid,
'time' => time_stamp,
'hash' => disposable_salted_hash( $uid, time_stamp )
)
echo 'setDomainCookie(' . json_encode(user_data) . ')'
第 5 步
然后执行回调函数,在mydomain.com
上设置cookie。最后,我们既可以刷新页面,也可以只使用 JavaScript 提醒用户他们已登录(最好两者兼有)。
function setDomainCookie( user_data )
if( user_data.success )
$.post('/setcookie', user_data, function()
location.reload(true);
mydomain.com/setcookie
类似于第 2 步。当然,这假设两个站点都可以访问相同的数据库(和代码)
if hash = disposable_salted_hash( $uid, time_stamp )
SELECT unique_value FROM users WHERE uid = $uid
set cookie on mydomain.com containing unique_value
第 6 步
下次用户刷新页面时,我们可以绕过JSON-P回调
if cookie on mydomain.com is valid
loggedin = true
else
delete cookie on mydomain.com
proceed to Step 3
退出
第 7 步
mydomain.com
上的链接应该转到central.com/logout
第 8 步
在central.com/logout
上,不仅 cookie 被删除,而且该用户的唯一值也被重置。用户被重定向回mydomain.com
delete cookie on central.com
UPDATE users SET unique_value = new_random_value() WHERE username = $username
第 9 步
现在唯一值被重置,上面的第6步失败,cookie也从mydomain.com
中删除,用户被有效注销。
注意事项
步骤 4 中的 central.com/check
具有
设置正确的标头,使其不被缓存。
用户登录时的步骤 3-5 可能会导致轻微延迟。明智的做法是刷新 和 显示他们已登录的某种 JavaScript 警报。步骤 3 中的脚本尽可能靠近顶部也很重要页面尽可能。
在第 5 步中,您可以选择在每个域上存储一个唯一的 cookie 值。
单独的central.com
域并不是必需的;你可以
如果您愿意,只需使用其他域之一作为中心域。
该领域的逻辑显然会有所不同。
要在 Internet Explorer 上运行,您需要 P3P 策略 附加到您的 cookie。
正如 IvanGusev 在 cmets 中指出的那样,这种方法的一个缺陷是,如果用户从设备 A 注销,它也会将他们从其他所有设备注销。
希望这对人们有所帮助。我很想收到
反馈,特别是如果有任何安全漏洞
方法。我认为黑客可以做的最糟糕的事情就是复制步骤 3-5 并在您不知情的情况下将您登录到 mydomain.com
,但那是无害的。
【讨论】:
优秀的答案。但是,我也想知道使用这种方法是否存在任何安全漏洞。希望比我更有经验的人加入.. 但是不同的设备呢?如果您在设备 A 上注销,B 会发生什么? @IvanGusev 是的,这是一个缺陷。它会将您从所有设备中注销。一种可能的解决方案是您可以为每个用户存储多个唯一密钥,并在他们从新设备登录时生成一个新密钥。 一个想法可能是仅在“mydomain”上存储唯一值。但需要决定何时存储:我认为应该是第 5 步。因此,如果用户在设备 A 上注销,则在设备 B 中,他将自动重新登录。以上是关于使用 JSONP 和 cookie 进行跨域登录的主要内容,如果未能解决你的问题,请参考以下文章