使用 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/checkjavascript调用。

<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 进行跨域登录的主要内容,如果未能解决你的问题,请参考以下文章

mui ajax登录怎么跨域

Vue中使用jsonp进行跨域请求

django+vue无法设置跨域cookies

单点登录认证原理及跨域cookie共享

正确面对跨域

sso单点登录都有哪些实现方式?