symfoBlog
понедельник, 31 января 2011 г.
среда, 15 октября 2008 г.
sfUser->addCredentials() портит CSRF-защиту
Однажды, долгим зимнем вечером столкнулся с такой проблемой: на формах появилась ошибка CSRF валидации. Недолгие копания в исходниках symfomy привели меня в функцию sfUser->addCredentials(), в которой вызывалась sfSessionStorage->regenerate():
Вот же блин, думаю, он идентификатор меняет, поэтому и не подходит CSRF ключь. А addCredentials я как раз начал использовать в одном из своих фильтров. Ну что ж, наследуем и дописываем класс:
Регистрируем в factories.yml:
Теперь все ок!
public function regenerate($destroy = false)
{
// regenerate a new session id
session_regenerate_id($destroy);
}
Вот же блин, думаю, он идентификатор меняет, поэтому и не подходит CSRF ключь. А addCredentials я как раз начал использовать в одном из своих фильтров. Ну что ж, наследуем и дописываем класс:
class sfMySessionStorage extends sfSessionStorage
{
public function regenerate($destroy = false)
{
// regenerate a new session id
// session_regenerate_id($destroy);
}
}
Регистрируем в factories.yml:
all:
storage:
class: sfMySessionStorage
param:
session_name: sid
Теперь все ок!
вторник, 14 октября 2008 г.
хранения сесси без куков
При содании wap-версии сайта, мне пришлось отказаться от хранения сесси в куках. Казалось бы нет ничего проще - пишем в .htaccess: 'php_value session.use_trans_sid 1' и идентификатор сессии автоматичеки дописывается ко всем url. Но при редиректе в action он, к сожалению, теряется. Исправить это можно немного дописав функцию redirect класса sfFrontWebController. Как обычно в lib'ах создаем sfMyFrontWebController.class.php с таким содержанием:
и регистрируем этот класс в файле factories.yml вместо sfFrontWebController:
Теперь сессия не потеряется!
class sfMyFrontWebController extends sfFrontWebController
{
public function redirect($url, $delay = 0, $statusCode = 302)
{
if( session_id() != '' && false === strpos($url, session_name()))
{
if( false !== strpos($url, '?') )
$url .= '&'.session_name().'='.session_id();
else
$url .= '?'.session_name().'='.session_id();
}
parent::redirect($url, $delay, $statusCode);
}
}
и регистрируем этот класс в файле factories.yml вместо sfFrontWebController:
all:
controller:
class: sfMyFrontWebController
Теперь сессия не потеряется!
воскресенье, 12 октября 2008 г.
symfony и XAMPP
По желанию, symfony можно подружить и с xampp-сервером. Порядок действия:
1. После установки xampp исправляем в httpd.conf - DocumentRoot "C:/xampp/htdocs"
2. Создаем папку C:\xampp\htdocs\localhost и копируем туда содержимое C:\xampp\htdocs
3. Устанавливаем symfony любым способом.
4. Проект создаем в C:\xampp\htdocs\proj1
5. Настраиваем виртуальный хост C:\xampp\apache\conf\extra\httpd-vhosts.conf
6. Не забываем добавить запись '127.0.0.1 prog1' в hosts.
Все готово - стартуем xampp!
1. После установки xampp исправляем в httpd.conf - DocumentRoot "C:/xampp/htdocs"
2. Создаем папку C:\xampp\htdocs\localhost и копируем туда содержимое C:\xampp\htdocs
3. Устанавливаем symfony любым способом.
4. Проект создаем в C:\xampp\htdocs\proj1
5. Настраиваем виртуальный хост C:\xampp\apache\conf\extra\httpd-vhosts.conf
NameVirtualHost *:80
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot C:/xampp/htdocs/localhost
ServerName localhost
ServerAlias www.localhost
ErrorLog C:/xampp/htdocs/localhost/error_log
CustomLog C:/xampp/htdocs/localhost/access_log common
</VirtualHost>
<VirtualHost *:80>
ServerAdmin webmaster@proj1
DocumentRoot C:/xampp/htdocs/proj1/web
ServerName proj1
ServerAlias www.proj1
ErrorLog C:/xampp/htdocs/proj1/log/error_log
CustomLog C:/xampp/htdocs/proj1/log/access_log common
</VirtualHost>
6. Не забываем добавить запись '127.0.0.1 prog1' в hosts.
Все готово - стартуем xampp!
symfony и Денвер
symfony прекрасно уживается с Денвером. Я устанавливаю его через PEAR. Проекты создаю в папке z:\usr\projects.
После инициализации делаю симлинк: z:\usr\projects\prog1\web -> z:\home\prog1\www
Еще один симлинк: PEAR\data\symfony\web\sf -> z:\home\prog1\www\sf
После инициализации приложений нужно исправить пути в index файлах (в папке web). А т.к. пути в Денвере вероятно отличаются от путей на рабочем сервере, использую такую проверку:
Так же не забудьте уточнить пути в ProjectConfiguration.class.php для подключения файла sfCoreAutoload.class.php, вероятно что-то вроде require_once('/usr/share/pear/symfony/autoload/sfCoreAutoload.class.php');
И если надо - делайте такую же проверку на ОС.
После инициализации делаю симлинк: z:\usr\projects\prog1\web -> z:\home\prog1\www
Еще один симлинк: PEAR\data\symfony\web\sf -> z:\home\prog1\www\sf
После инициализации приложений нужно исправить пути в index файлах (в папке web). А т.к. пути в Денвере вероятно отличаются от путей на рабочем сервере, использую такую проверку:
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
require_once('/usr/projects/prog1/config/ProjectConfiguration.class.php');
else
require_once('[реальный путь на сервере]/ProjectConfiguration.class.php');
Так же не забудьте уточнить пути в ProjectConfiguration.class.php для подключения файла sfCoreAutoload.class.php, вероятно что-то вроде require_once('/usr/share/pear/symfony/autoload/sfCoreAutoload.class.php');
И если надо - делайте такую же проверку на ОС.
пятница, 10 октября 2008 г.
Constrains и загрузка данных
Когда я достаточно усложнил fixtures для тестирования, то при загрузке fixtures:
появилась ошибка c constrains - Propel не мог просто так очистить БД.
Нашел выход в небольшом дописывании класса sfPropelData - создаем myPropelData.class.php и кладем его в lib'ы:
и далее в тестах используем
$data = new sfPropelData();
$data->loadData(sfConfig::get('sf_test_dir').'/fixtures/');
появилась ошибка c constrains - Propel не мог просто так очистить БД.
Нашел выход в небольшом дописывании класса sfPropelData - создаем myPropelData.class.php и кладем его в lib'ы:
class myPropelData extends sfPropelData
{
public function loadData($directoryOrFile = null, $connectionName = 'propel')
{
$con = Propel::getConnection($connectionName);
$query = 'SET FOREIGN_KEY_CHECKS = 0;';
$statement = $con->prepareStatement($query)->executeQuery();
parent::loadData($directoryOrFile, $connectionName);
$query = 'SET FOREIGN_KEY_CHECKS = 1;';
$statement = $con->prepareStatement($query)->executeQuery();
}
}
и далее в тестах используем
$data = new myPropelData();
$data->loadData(sfConfig::get('sf_test_dir').'/fixtures/');
четверг, 9 октября 2008 г.
Запоминание пользователя при входе
В комплекте с sfGuardPlugin есть фильтр sfGuardBasicSecurityFilter для 'запоминания' пользователя при авторизации. Этот фильтр необходимо указать в filters.yml в качсестве security фильтра.
Все бы хорошо, но security фильтр запускается только при входе на защищенные страницы (is_secure: on). Учитывая что для первой (стартовой) страницы сайта защита обычно отключается - то фильтр не запускается и пользователь не опознается. Если продолжить путешествие по сайту и пройти в защищенную область - фильтр сработает и пользователь опознается.
Но как авторизировать его с первого раза?
Копируем sfGuardBasicSecurityFilter.class.php под именем myRememberFilter.class.php в папку lib своего application. Потом вносим небольшие изменения:
Теперь остается в filters.yml прописать его как обычный фильр:
Теперь пользователи опознаются сразу!
Все бы хорошо, но security фильтр запускается только при входе на защищенные страницы (is_secure: on). Учитывая что для первой (стартовой) страницы сайта защита обычно отключается - то фильтр не запускается и пользователь не опознается. Если продолжить путешествие по сайту и пройти в защищенную область - фильтр сработает и пользователь опознается.
Но как авторизировать его с первого раза?
Копируем sfGuardBasicSecurityFilter.class.php под именем myRememberFilter.class.php в папку lib своего application. Потом вносим небольшие изменения:
class myRememberFilter extends sfFilter
{
public function execute ($filterChain)
{
if ($this->isFirstCall() and !$this->getContext()->getUser()->isAuthenticated())
{
if ($cookie = $this->getContext()->getRequest()->getCookie(sfConfig::get('app_sf_guard_plugin_remember_cookie_name', 'sfRemember')))
{
$c = new Criteria();
$c->add(sfGuardRememberKeyPeer::REMEMBER_KEY, $cookie);
$rk = sfGuardRememberKeyPeer::doSelectOne($c);
if ($rk && $rk->getSfGuardUser())
{
$this->getContext()->getUser()->signIn($rk->getSfGuardUser());
}
}
}
$filterChain->execute();
}
}
Теперь остается в filters.yml прописать его как обычный фильр:
...
security: ~
# generally, you will want to insert your own filters here
remember:
class: myRememberFilter
...
Теперь пользователи опознаются сразу!
Подписаться на:
Сообщения (Atom)