Междоменный вход с использованием JSONP и файлов cookie

Как я могу разрешить пользователям регистрироваться в одном домене и автоматически регистрироваться в других доменах без необходимости отправки формы в каждый домен?

Ответ 1

Мы все знаем, что файлы cookie недоступны для междоменного доступа, так как это представляет угрозу безопасности. Однако, используя некоторые обманки, есть способы обойти это. В основном мы устанавливаем cookie для пользователя в центральном домене, проверяя существование этого файла cookie с помощью script, а затем используя обратный вызов JSON-P для копирования этого файла cookie на другие домены. Подробнее:

Вход в систему

Шаг 1

<form>, отображаемый на mydomain.com (или myotherdomain.com и т.д.), должен быть POST до central.com/login

Шаг 2

В central.com/login имя пользователя и пароль проверены, а cookie установлен в домене central.com, содержащем уникальное значение для этого пользователя. Затем пользователь перенаправляется обратно на 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 может вставить этот script и получить информацию о пользователе. (Установка соответствующих заголовков 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

Затем выполняется функция обратного вызова, установив файл 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, но и уникальное значение для этого пользователя reset. Пользователь перенаправляется обратно на mydomain.com

delete cookie on central.com
UPDATE users SET unique_value = new_random_value() WHERE username = $username

Шаг 9

Теперь, когда уникальное значение reset, Шаг 6 сверху не работает, файл cookie также удаляется из mydomain.com, и пользователь фактически вышел из системы.

Примечания

  • Очень важно, чтобы central.com/check от Шаг 4 имел правильный набор заголовков, чтобы он не был кеширован.

  • Шаги 3-5, когда пользователь регистрируется, могут вызвать небольшую задержку. Разумно как обновить, так и показать какое-то напоминание о том, что они вошли в систему. Важно также, чтобы script от Шаг 3 был как можно ближе к верхней части страницы.

  • В Шаге 5 вы можете дополнительно сохранить уникальное значение cookie для каждого домена.

  • Отдельный домен central.com не нужен; ты можешь просто используйте один из других доменов в качестве центрального домена, если хотите. Логика для этого домена, очевидно, была бы иной.

  • Для этого в Internet Explorer вам понадобится политика P3P прикрепленных к вашим файлам cookie.

  • Как отмечает ИванГусев в комментариях, один из недостатков этого подхода заключается в том, что если пользователь выходит из устройства A, он также выведет их из любого другого устройства.

  • Надеюсь, это полезно людям. Мне было бы очень интересно получить обратной связи, особенно если есть какие-либо недостатки безопасности из этого метод. Я думаю, худшее, что может сделать хакер, это повторить шаги 3-5 и войти в mydomain.com, не зная, но это было бы безвредно.