Единый вход Django и сайт Php: междоменный вход?

Я создаю небольшое приложение в качестве службы в django, и сейчас самое время интегрировать его в некоторые клиентские веб-приложения PHP.

Наш клиент A из домена www.a.com выполняет собственную аутентификацию для своих пользователей и, вероятно, использует файлы cookie для сеансов.

Как я могу сделать так, чтобы зарегистрированные пользователи из его домена также вошли в мой домен приложения Django www.b.com/clientA/?

Я вижу, как я могу заставить их повторно войти в мой домен и использовать authbackend для проверки учетных данных с доменом A, но это означает, что пользователю придется дважды вводить свой логин/пароль: на www.a.com и www.b.com.

Я думаю, что доступ к куки из домена www.a.com невозможен из соображений безопасности.

Как бы вы справились с этим?


person coulix    schedule 19.07.2009    source источник
comment
Можно ли вообще изменить приложение PHP?   -  person oggy    schedule 20.07.2009
comment
Кстати, правильный термин - Djangonauts   -  person lprsd    schedule 21.07.2009


Ответы (4)


Вы правы, предполагая, что файлы cookie из другого домена недоступны. Однако, если он находится на поддомене, вы должны иметь доступ к файлам cookie, если они установлены правильно.

Если вам абсолютно необходимо иметь их на совершенно разных доменах, это будет немного сложно. Если вы не можете изменить существующий PHP-код, вы можете практически забыть о нем.

Одним из вариантов может быть использование OpenID — это может быть самый простой способ решить эту проблему, поскольку существуют библиотеки OpenID, доступные для PHP и Python. OpenID позволит вам использовать единый вход, такой как аутентификация, и, поскольку он уже используется на различных сайтах, он проверен и работает.

Другой вариант — написать собственную систему единого входа.

Основная идея заключается в том, что когда пользователь заходит на ваш сайт, вы направляете его на сайт авторизации. Это может быть либо в конце PHP или Python, либо отдельно. Здесь пользователь войдет в систему, а затем логин сгенерирует секретный ключ — это может быть хэш, случайная строка, что угодно, если это непредсказуемо — и пользователь перенаправляется обратно на основной сайт с ключом.

Затем основной сайт видит, что у пользователя есть ключ, и отправляет запрос на сайт входа в систему за кулисами, чтобы проверить ключ пользователя.

Теперь пользователь авторизован на одном сайте. Когда пользователь посещает второй сайт, он также перенаправляет пользователя на сайт входа. Поскольку пользователь уже вошел в систему, сайт входа просто перенаправляет пользователя обратно с новым секретным ключом, а второй сайт проверяет его с сайта входа, и теперь пользователь входит в систему без необходимости вводить свои учетные данные еще раз.

person Jani Hartikainen    schedule 19.07.2009
comment
Большинство клиентов уже имеют свою схему аутентификации и не будут использовать openid, это слишком чуждо им. Мне нравится ваше последнее решение с третьим центральным сайтом входа, за исключением того, что оно требует, возможно, слишком много изменений на клиенте, если я не предоставлю для него PHP-код. - person coulix; 20.07.2009
comment
Вы можете использовать существующую PHP-аутентификацию клиента для второго варианта. Вам просто нужно изменить его, чтобы он мог генерировать секрет и общаться с другим сайтом. - person Jani Hartikainen; 20.07.2009
comment
Один маленький вопрос, в котором я не уверен. Когда страница входа дает мне секретный ключ, я передаю его на исходную страницу в виде переменной GET. Теперь я делаю запрос с помощью Ajax, возможно, к домену страницы регистрации, спрашивая, не могли бы вы проверить этот ключ? Он ответит да, это действительно, тогда что? Как мне зарегистрировать пользователя в моем домене? - person coulix; 21.07.2009
comment
Может быть, заставив сервер входа возвращать имя пользователя и ключ, когда ключ действителен? - person coulix; 21.07.2009
comment
Не делайте этого с Ajax. Это должно быть сделано на стороне сервера, чтобы быть более безопасным и надежным. И да, вы можете вернуть любые данные, которые пожелаете - вероятно, идентификатор пользователя или что-то, по чему вы можете его идентифицировать, - это хорошая идея. - person Jani Hartikainen; 21.07.2009
comment
Серверная часть с https? но как я могу убедиться, что никто не может подделать поддельное признание, отправляя случайные идентификаторы? - person coulix; 21.07.2009
comment
Понял, извините, спасибо! его сервер к серверу, ничего общего с Ajax и клиентом. - person coulix; 21.07.2009

Итак, вот как аутентифицировать пользователя Django с PHP или как «прочитать» пароль Django с PHP.

Я думаю, что OpenID — лучшее решение, но сегодня мне пришлось аутентифицировать пользователей Django в приложении PHP, использующем ту же базу данных, и вот как я решил:

<?php

/* Generates crypted hash the same way as Django does */
function get_hexdigest($algorithm, $salt, $raw_password) {
   if (!array_in($algorithm, array('md5', 'sha1'))) {
       return false;
   }
   return $algorithm($salt.$raw_password);
}

/* Checks if password matches the same way Django does */
function check_password($raw_password, $django_password) {
    list($algorithm, $salt, $hsh) = explode('$', $django_password);
    return get_hexdigest($algoritm, $salt, $raw_password) === $hsh;
}

?>

Ключ в том, чтобы понять формат, в котором Django сохраняет пароли, а именно:

[алгоритм]$[соль]$[хэш]

Так, например, у меня был пользователь «admin» с паролем «admin», а поле пароля в строке auth_user было:

sha1$63a11$85a93f217a72212b23fb0d5b95f3856db9575c1a

Алгоритм — «sha1», случайно сгенерированная соль — «63a11», а зашифрованный хеш — «85a93f217a72212b23fb0d5b95f3856db9575c1a».

Итак, кто производит зашифрованный хэш в PHP? Вы просто объединяете соль и необработанный пароль и хешируете их с помощью алгоритма, в данном случае sha1:

<?php 

$salt = '63a11';
$pass = 'admin';

echo sha1($salt.$admin); // prints "85a93f217a72212b23fb0d5b95f3856db9575c1a"

?>

Это было несложно! Я получил это, прочитав соответствующий код в исходниках Django.

person gnrfan    schedule 06.03.2010

Вы можете использовать перенаправления HTTP туда и обратно. Когда пользователь заходит на www.b.com и файлы cookie не установлены, выполняется перенаправление на www.a.com/crosslogin?return_to=URL&challenge=stuff. На a.com проверьте наличие файла cookie и, если он установлен, перенаправьте на URL?verified=otherstuff.

Это потребует криптографии запрос-ответ, если вы хотите, чтобы пользователи не подделывали аутентификацию. a.com и b.com должны будут установить общий секрет, и все будет зашифровано с помощью этого секрета. другие вещи также зашифрованы этим секретом; при расшифровке выдает кортеж (stuff, user). b.com, возможно, потребуется сохранить кеш повторов, чтобы другие материалы можно было использовать только один раз.

person Martin v. Löwis    schedule 19.07.2009

Я вижу следующие варианты:

1) Используйте Open ID, как предложил Яни Харткайнен. Это может быть лучшим решением.

2) Использовать один домен через обратный http прокси:

Используйте обратный http-прокси, чтобы разместить приложение php и ваше приложение django в одном домене. Это даст вам доступ к файлам cookie сеансов вашего php-приложения.

Как только вы получите идентификатор сеанса php в своем приложении django, запустите запрос к приложению PHP с установленным файлом cookie сеанса, чтобы проверить, кто вошел в систему. К сожалению, это может потребовать очистки html или реализации простой службы в приложении PHP, которая будет возвращать имя вошедший пользователь. Как только вы войдете в систему, вы можете авторизовать его в своем приложении django.

3) Идентификатор сеанса PHP передается через GET:

Измените приложение PHP, чтобы добавить идентификатор сеанса в качестве параметра для ссылок на ваше приложение django. Например, попросите клиентов ссылаться на ваш веб-сайт следующим образом:

<yourwebsite.com>/?client_session_id=<session_id>&client_name=<client_name>

Как только вы получите идентификатор сеанса, вы можете аутентифицировать пользователя, как описано в пункте 2.

person Piotr Czapla    schedule 19.07.2009