Сложная интеграция устаревшего приложения PHP и нового приложения Ruby on Rails - PullRequest
2 голосов
/ 28 января 2009

У нас есть старое устаревшее PHP-приложение. Теперь я хочу написать новый модуль приложения, используя Ruby on Rails.

Развертывание является одной из проблем. Я предполагаю, что должно быть возможно запустить приложение PHP (через mod_php) и приложение RoR (через mod_proxy / mongrel) на одном сервере Apache. Я не хочу использовать mod_rails, потому что он требует запуска php через fcgi. Так что есть риск что-то сломать. И PHP, и RoR будут использовать одну и ту же БД.

Сложная задача - как передать информацию для входа из приложения PHP в приложение RoR. Пользователи входят в PHP, и их информация хранится в данных сессии PHP. Приложение RoR будет размещено в подкаталоге основного приложения PHP (например, www.example.com/railsapp). Поэтому RoR должен получать все файлы cookie HTTP. И вопрос в том, как извлечь данные сеанса PHP из приложения RoR.

Выше это только моя первая идея, которая довольно плоха из-за возможных условий гонки между модом PHP и RoR. Я могу изменить приложение PHP, чтобы хранить некоторую информацию в БД, когда пользователь входит в систему. Но я не знаю, как обрабатывать случай, когда истек срок действия данных сеанса PHP и некоторые данные в БД должны быть обновлены (выйти из системы). *

Кто-нибудь решал подобную проблему? Или, по крайней мере, может указать наиболее перспективное направление?

Обновление: должна быть возможность сконфигурировать mod_php для хранения данных сеанса в БД sql. Таким образом, не будет гоночных условий. Двигатель DB должен предотвращать условия гонки.

Update2: на самом деле возможно использовать mod_rails с Apache в режиме prefork. Что требуется от mod_php. Для mod_rails просто рекомендуется запускать Apache в режиме mpm. Таким образом, все развертывание приложений PHP / RoR значительно упрощается.

Ответы [ 5 ]

2 голосов
/ 28 января 2009

Во-первых, если вы размещаете приложение rails в подкаталоге, можно использовать mod_rails. В вашей конфигурации для сайта PHP вы можете иметь местоположение, в котором есть корень для rails.

<Location /railsapp>
  DocumentRoot /.../app/public
</Location>

Чтобы перевести сеанс на сторону рельсов, вы можете либо создать страницу соединения на рельсах, вызвать ее со стороны PHP и передать некоторые данные для входа в систему. Вам просто нужно защитить эту страницу от любого запроса не от localhost (это легко сделать).

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

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

PHP

$key = md5hash($user_id . $user_password_hash . $timestamp)
$url = "/railsapp/proxy?userid=" . $user_id . "&key=" . $key . "&page=home%2Fwelcome"
<a href="<$ $url $>">Rails App</a>

Рельсы

map.proxy 'proxy', :controller => 'proxy', :action => 'connect'

class ProxyController < ActionController::Base
  def connect
    key = ...
    if params[:key] == key
      login_user params[:userid]
      redirect_to params[:page]
    else
      render :nothing, :status => 403
    end
  end
end
2 голосов
/ 29 января 2009

Я уже делал смешанное приложение PHP / RoR (старый PHP-код, новые функции RoR, так как материал, требующий исправления, был заново реализован). Это на самом деле не так уж и сложно - вы просто обслуживаете PHP как обычные файлы и используете обработчик 404 для перенаправления всего остального в приложение Rails.

Что касается данных сеанса, вы можете поместить их в БД, но если вы хотите писать / находить процедуры для чтения и записи форматированных данных PHP, PHP использует flock() чтобы убедиться, что нет никаких условий гонки при чтении / записи файла данных сеанса. Сделайте то же самое в своем Rails-приложении, чтобы уменьшить боль.

1 голос
/ 28 января 2009

Во-первых, кажется, что вы напрашиваетесь на проблему, смешивая две технологии. Мое первое предложение «не делай этого».

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

Если ваше приложение выполняет относительно мало обращений к базе данных и, следовательно, имеет мало свободного времени, вы можете выполнить дополнительный запрос к таблице сеанса при каждом просмотре страницы хотя бы на определенных страницах. Это означает дополнительный запрос и загруженное приложение, которое является проблемой. Альтернативой обычно является задание cron, которое периодически запускается для очистки таблицы устаревших записей. Эти периодические задания по очистке также могут запускаться только при выполнении определенных других задач (например, при входе пользователя в систему, который часто бывает немного медленным, так как вам необходимо настроить данные сеанса).

0 голосов
/ 28 октября 2009

1) Я успешно использую Passenger и mod_php одновременно на одном prefork Apache, как на компьютере разработчика, так и на сервере.

2) Я бы подключал приложения через последовательность запросов / ответов HTTP или, возможно, через общие ключи memcached.

0 голосов
/ 28 октября 2009

Эй, я всегда думал, что это на самом деле довольно распространенная проблема для тех, кто переходит на ruby ​​с php, у которых есть легкие приложения / данные в php, и я удивлен, что их не спрашивают больше.

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

1) Используйте openid для обработки вашего логина, чтобы вам не пришлось беспокоиться о развертывании собственного решения. Либо запустите свой собственный сервер openid, либо используйте Google, Yahoo и т. Д. Запустите каждое из ваших приложений в качестве уникального субдомена. Есть открытые плагины / код для rails и php, и это проверенный и проверенный стандарт безопасности

2) Используйте memcached для хранения сеансов входа в систему (в отличие от БД). Иметь страницу входа (либо в приложении php, либо в приложении rails). Доступ к вашему ruby-приложению или php-приложению будет таким:

a) Пользователь пытается получить доступ к защищенной странице входа в систему

b) Приложение проверяет свои собственные данные сеанса, чтобы увидеть, вошел ли пользователь в систему

c) Если существуют правильные данные сеанса, пользователь входит в систему и приложение продолжает работу

d) Если приложение не может найти текущий сеанс входа, проверяет наличие cookie браузера

e) Затем приложение проверяет memcache для этого ключа cookie.

f) если ключ cookie существует, то пользователь должен войти в систему (в противном случае происходит переадресация на страницу входа)

g) приложение получает user_id из memcached (хранится как ключ cookie), чтобы знать, какой пользователь вошел в систему

h) приложение устанавливает сеанс входа в систему, поэтому ему не нужно снова проходить мимо c, если время сеанса не истекло

Это слишком упрощенная версия того, что происходит, но работает. Я бы использовал memcached в этом сценарии, потому что он имеет автоматическое истечение значений, которые вы определяете, и чертовски быстро. Помните, не передавайте имена пользователей и пароли между приложениями или даже идентификаторами пользователей. Передайте уникальный ключ, который является просто указателем на информацию, хранящуюся в вашей БД / memcached

...