Создание API для единого входа (SSO) с сторонним сайтом

18 июл. 2012 г., 20:42:14
Просмотры: 19.6K
Голосов: 13

Мой сайт должен интегрироваться со сторонним программным обеспечением, которое будет размещено на собственном поддомене, хостингом которого занимается компания-разработчик. Мне нужно предоставить сторонним разработчикам конечную точку API, через которую они смогут делать запросы к моему WordPress-сайту, чтобы пользователи моего сайта могли получить доступ к поддомену.

Другому сайту необходимо аутентифицировать пользователей моего сайта через какой-то API-интерфейс.

Я не совсем уверен, с чего начать, но мне кажется, что эту задачу уже решили люди умнее меня. Заранее спасибо за помощь!

2
Комментарии

Какие API-вызовы потребуются? Что вы пытаетесь сделать? Вы смотрели поддержку XML-RPC в WordPress (http://codex.wordpress.org/XML-RPC_Support) ?

anu anu
19 июл. 2012 г. 03:17:50

Другому сайту необходимо проверять/аутентифицировать пользователей с моего сайта на WordPress.

emersonthis emersonthis
19 июл. 2012 г. 16:31:33
Все ответы на вопрос 1
11
16

Проблемы межсайтового скриптинга (XSS)

Вы не можете передавать аутентификационные куки WordPress между доменами. Также не рекомендуется хранить пароли в открытом виде для автоматического входа в другую установку WordPress. Поэтому пользователям придётся входить в WordPress, а затем получать статус их входа через API-эндпоинт с третьего сайта. Это позволяет WordPress обрабатывать всю аутентификацию. Такой подход достаточно безопасен, так как пользователь должен физически войти в WordPress, чтобы API-эндпоинт предоставил данные третьей стороне.

Создание API-эндпоинта

Ознакомьтесь с моей статьей: http://coderrr.com/create-an-api-endpoint-in-wordpress/

Также вы можете посмотреть демонстрацию кода здесь: https://gist.github.com/2982319

Вам нужно будет разработать логику под свои нужды, но этот метод позволит создать эндпоинт, через который можно передавать любые данные из WordPress.

Поскольку WordPress используется для аутентификации, можно проверить статус входа через функцию is_user_logged_in(). Если вход выполнен, можно вернуть объект пользователя с необходимыми данными для третьей стороны.

Вход с третьей стороны

С третьего сайта можно добавить ссылку на страницу входа для удобства, используя параметр redirect_to. После входа пользователь будет перенаправлен обратно на сторонний сайт.

http://sub.yourdomain.com/wp-login.php?redirect_to=http%3A%2F%2Fwww.third-party-domain.com

Удалённый вход

Если требуется авторизовывать пользователей в WordPress с третьего сайта, можно использовать функции WordPress, описанные здесь: http://kuttler.eu/code/log-in-a-wordpress-user-programmatically/

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

Третья сторона отправляет запрос с временной меткой и токеном, сгенерированным на основе общего секрета:

$shared_secret = 'foobar'; //не передавать этот ключ в API-эндпоинт
$timestamp = time();
$token = md5($shared_secret.$time_stamp);

Установка WordPress получает запрос:

$shared_secret = 'foobar';
$timestamp = esc_attr($_GET['timestamp']);

if((time() - $timestamp) > 30) # Порог 30 секунд
    //здесь можно обработать истёкший токен!

$token = md5($share_secret.$timestamp);
$token_to_check = esc_attr($_GET);

if($token == $token_to_check)
    //аутентификация успешна!
18 июл. 2012 г. 21:43:07
Комментарии

Довольно уверен, что стороннее ПО не имеет никакого отношения к WP, так что по сути это единый вход (SSO), но с WordPress в роли провайдера аутентификации.

anu anu
19 июл. 2012 г. 17:03:02

@anu: Верно.

emersonthis emersonthis
20 июл. 2012 г. 17:52:18

@Brian: Меня заинтересовала идея перехода на мультисайтовую установку, но я не до конца понимаю ваш аргумент насчёт cookies. Всё, что нужно - чтобы стороннее ПО могло проверить, что его пользователь действительно является моим пользователем. В остальном ПО самодостаточно и может использовать собственные cookies или что-то ещё.

emersonthis emersonthis
20 июл. 2012 г. 17:56:55

@Emerson Теперь я понимаю. Извините за путаницу. Вы можете использовать идею конечной точки, которую я создал, и использовать общий токен в метаданных пользователя для аутентификации. Возвращайте JSON-ответ третьей стороне, если пользователь существует.

Brian Fegter Brian Fegter
20 июл. 2012 г. 20:18:20

Спасибо, Brian. Я внимательнее изучил ваш код и, кажется, начинаю понимать ваше решение. Не могли бы вы показать небольшой пример кода, чтобы проиллюстрировать, как ваш плагин будет работать в моем приложении? Я посмотрел исходный код, но пока не до конца разобрался.

emersonthis emersonthis
21 июл. 2012 г. 17:26:00

Если быть более конкретным, меня интересует, как адаптировать ваш плагин для моих целей. Нужно ли заменить это: protected $api = 'http://pugme.herokuapp.com/bomb?count='; на protected $api = http://mydomain.com/api/..., поскольку мой скрипт будет проверять данные в моей базе данных, а не в стороннем API... ?

emersonthis emersonthis
23 июл. 2012 г. 20:15:21

@Emerson Вам действительно не нужно использовать переменную api, так как вы будете делать запрос к базе данных WP вместо использования конечной точки для стороннего API. Вы можете просто удалить это. Вся магия происходит в add_rewrite_rule(); Если у вас есть дополнительные вопросы, свяжитесь со мной на моем сайте.

Brian Fegter Brian Fegter
23 июл. 2012 г. 20:19:38

Отлично. Так и сделаю.

emersonthis emersonthis
23 июл. 2012 г. 20:25:19

@Brian огромное спасибо, это отличное решение! У меня есть вопрос. Должен ли запрос от стороннего приложения к конечной точке выполняться на стороне клиента? Я попробовал это локально: когда я делаю запрос прямо в браузере, я получаю правильный ответ "пользователь авторизован" от конечной точки, но когда я делаю это со страницы PHP - нет. Я предполагаю, что мне нужно запрашивать статус авторизации из браузера, потому что серверная сторона не знает о статусе.

And Finally And Finally
7 июл. 2014 г. 18:49:47

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

And Finally And Finally
15 июл. 2014 г. 18:42:09

Очень хорошее решение. Может возникнуть проблема, если приложения установлены на разных серверах и по какой-то причине время на каждой машине отличается. Я бы предложил использовать counter вместо time() и передавать его с запросом. Обе стороны сохраняют последний переданный счетчик, и когда API получает запрос с новым счетчиком, он проверяет, что новый больше предыдущего. Таким образом, задержка не может нанести вред.

guyaloni guyaloni
29 дек. 2014 г. 13:24:47
Показать остальные 6 комментариев