authentication - 使用JSONP和Cookie进行跨域登录

标签 authentication cookies login cross-domain jsonp

如何允许用户登录一个域并自动登录我的其他域,而不必在每个域上提交表单?

最佳答案

我们都知道Cookie无法跨域访问,因为这会带来安全风险。但是,使用一些技巧,可以解决此问题。基本上,我们在中央域上为用户设置一个cookie,使用脚本检查该cookie的存在,然后使用JSON-P回调将该cookie复制到其他域。更详细地:

在登录

步骤1

显示在<form>(或mydomain.com等)上的myotherdomain.com应该发布到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,我们将javascript调用嵌入到central.com/check
<script type="text/javascript" src="http://central.com/check"></script>

步骤4

central.com/check上,我们检查是否为用户设置了唯一的cookie。然后,我们嵌入一个JavaScript回调(JSON-P),通知mydomain.com用户已登录。不包括敏感的用户数据,否则hacker.com可以嵌入此脚本并获取用户的信息。 (将适当的Access-Control header 设置为仅允许经过验证的域可以减轻这种风险。)相反,我们根据时间戳创建一个可处理的哈希,以便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

然后执行回调函数,将cookie设置为mydomain.com。最后,我们可以刷新页面,或者只是使用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必须具有
    设置正确的 header ,以便不进行缓存。
  • 用户登录时的步骤3-5可能会引起轻微的延迟。刷新并显示某种JavaScript警报已登录是明智的。步骤3 中的脚本尽可能靠近页面顶部也很重要。
  • 步骤5 中,您可以选择在每个域上存储唯一的cookie值。
  • 并不是真正需要单独的central.com域。你可以
    只需将其他域之一用作中心域即可。
    该域的逻辑显然会有所不同。
  • 为了在Internet Explorer上运行,您需要P3P策略
    附加到您的Cookie。
  • 正如IvanGusev在评论中指出的那样,此方法的一个缺点是,如果用户注销设备A,它也将使它们注销其他所有设备。
  • 希望这对人们有所帮助。我会很感兴趣收到
    反馈,尤其是在此过程中存在任何安全缺陷时
    方法。我认为,黑客可能做的最糟糕的事情是复制第3-5步,并在您不知情的情况下将您登录到mydomain.com,但这将是无害的。
  • 关于authentication - 使用JSONP和Cookie进行跨域登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10956488/

    相关文章:

    angular - 隐藏基于 Authentication Angular 2 的链接

    django - 标准 Django 登录身份验证不应该区分大小写吗?

    Django 使用带有 djoser 的电子邮件身份验证进行登录

    django - 在 cookie 中保存身份验证 token (Django Rest Framework + React)

    apache - 自定义 apache tomcat 身份验证所需的弹出窗口

    python - 如何在同一子域上获取不同的 Django 应用程序以共享 session cookie?

    android - Google Play 服务可以在应用内使用 cookie 吗?

    javascript - 如何将 cookie 中存储的数字限制为小数点后 2 位?

    login - 在 Keycloak 禁用多重登录

    php - 如何在 yii 框架中使用登录表单进行身份验证