PdoSessionHandler FOSUserBundle登录
我已实现将会话保存到数据库中,但问题是,在我将其应用到我的应用程序后,登录不起作用,它似乎没有根据以下日志获取实体: [2014-02-26 05:47:10]request.INFO:匹配的路由“fos\u用户安全检查”(参数:“\u控制器”:“fos\UserBundle\controller\SecurityController::checkAction”,“\u路由”:“fos\u用户安全检查”[] [2014-02-26 05:47:10]event.DEBUG:通知侦听器“Symfony\Component\HttpKernel\EventListener\LocaleListener::onKernelRequest”的事件“kernel.request”。[][] [2014-02-26 05:47:10]event.DEBUG:向侦听器“Symfony\Component\Security\Http\Firewall::onKernelRequest”通知事件“kernel.request”。[][] [2014-02-26 05:47:10]security.INFO:身份验证请求失败:CSRF令牌无效。[][] [2014-02-26 05:47:10]security.DEBUG:重定向到/登录[] 与默认的sessionhandler不同,默认的sessionhandler可以正常登录: [2014-02-26 07:10:07]request.INFO:匹配的路由“fos_用户安全检查”(参数:“_控制器”:“fos\UserBundle\controller\SecurityController::checkAction”,“_路由”:“fos_用户安全检查”[] [2014-02-26 07:10:07]event.DEBUG:通知侦听器“Symfony\Component\HttpKernel\EventListener\LocaleListener::onKernelRequest”的事件“kernel.request”。[][] [2014-02-26 07:10:07]event.DEBUG:向侦听器“Symfony\Component\Security\Http\Firewall::onKernelRequest”通知事件“kernel.request”。[][] [2014-02-26 07:10:07]条令调试:选择t0.username作为用户名1,t0.username\u canonical作为用户名\u canonical 2,t0.email作为电子邮件3,t0.email\u canonical作为电子邮件\u canonical 4,t0.enabled作为启用,t0.salt作为密码,t0.last作为最后登录,t0.locked作为锁定,t0.expired作为过期,t0.expires_at AS expires_at 11,t0.confirmation_to AS confirmation_token 12,t0.password_at AS password_required_at 13,t0.roles AS roles 14,t0.credentials_过期为credentials_expired_at AS credentials_过期为credentials_at 16,t0.id为id17,t0.first_name为first_name为first_name 18,t0.last_为last_name为last_19,t0.date_创建为date_从用户t0创建20,其中t0.username_canonical=?限制1[“rainercedric23”][] [2014-02-26 07:10:07]security.INFO:用户“rainercedric23”已成功通过身份验证[] 如您所见,日志显示,与默认会话处理程序相比,PdoSessionHandler与条令没有交互。我还注意到,在提交表单之后,侦听器无法获取导致身份验证请求失败的CSRF令牌 更新: 这是不带CSRF令牌的日志,它对用户进行身份验证,但在用户离开页面后,它会在数据库中写入另一个会话,从而使下一个页面用户令牌再次匿名: [2014-02-26 07:39:59]security.INFO:用户“rainercedric23”已成功通过身份验证[] [2014-02-26 07:39:59]security.DEBUG:从会话中读取SecurityContext[] [2014-02-26 07:39:59]security.DEBUG:从用户提供程序重新加载用户。[][] [2014-02-26 07:39:59]条令调试:选择t0.username作为用户名1,t0.username作为用户名2,t0.email作为电子邮件3,t0.email作为电子邮件4,t0.enabled作为启用,t0.salt作为密码7,t0.last作为最后登录,t0.locked作为锁定,t0.expired作为过期,t0.expires_at AS expires_at 11,t0.confirmation_to AS confirmation_token 12,t0.password_at AS password_required_at 13,t0.roles AS roles 14,t0.credentials_过期为credentials_expired_at AS credentials_过期为credentials_at 16,t0.id为id17,t0.first_name为first_name为first_name 18,t0.last_为last_name为last_19,t0.date_创建为date_从用户t0创建20,其中t0.id=?限制1[7][] [2014-02-26 07:39:59]security.DEBUG:已从用户提供程序重新加载用户名“rainercedric23”。[][] [2014-02-26 07:40:00]security.DEBUG:在会话中写入SecurityContext[] [2014-02-26 07:40:00]security.INFO:使用匿名令牌填充SecurityContext[] [2014-02-26 07:40:00]security.DEBUG:访问被拒绝(用户未通过完全身份验证) [2014-02-26 07:40:00]security.DEBUG:调用身份验证入口点[][]PdoSessionHandler FOSUserBundle登录,session,symfony,doctrine-orm,Session,Symfony,Doctrine Orm,我已实现将会话保存到数据库中,但问题是,在我将其应用到我的应用程序后,登录不起作用,它似乎没有根据以下日志获取实体: [2014-02-26 05:47:10]request.INFO:匹配的路由“fos\u用户安全检查”(参数:“\u控制器”:“fos\UserBundle\controller\SecurityController::checkAction”,“\u路由”:“fos\u用户安全检查”[] [2014-02-26 05:47:10]event.DEBUG:通知侦听器“Symfo
有没有办法解决这个问题?谢谢~ 多亏了Daniel15,我在包中创建了一个customPdoSessionHandler,找到了一个解决方案(我调整了一些代码,以便能够在Symfony2中使用它),我将PdoSessionHandler作为customPdoSessionHandler的basehandler
<?php
namespace foo\barBundle\Handler;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler as baseHandler;
/**
* PDO Session Handler
* @author Daniel15 <dan.cx>
*
* This class is actually static, but since PHP doesn't support static classes, abstract is close
* enough. You do not instantiate the class; you just call the static "init" method.
*/
class CustomPdoSessionHandler extends baseHandler {
private static $db;
private static $oldData;
private $pdo;
private $dbOptions;
public function __construct(\PDO $pdo, array $dbOptions = array())
{
if (!array_key_exists('db_table', $dbOptions)) {
throw new \InvalidArgumentException('You must provide the "db_table" option for a PdoSessionStorage.');
}
if (\PDO::ERRMODE_EXCEPTION !== $pdo->getAttribute(\PDO::ATTR_ERRMODE)) {
throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__));
}
$this->pdo = $pdo;
$this->dbOptions = array_merge(array(
'db_id_col' => 'session_id',
'db_data_col' => 'data',
'db_time_col' => 'last_activity',
), $dbOptions);
}
/**
* Session open handler
* @param string Path to save session to
* @param string Name of the session
*/
public function open($save_path, $session_name) {
// Nothing
return true;
}
/**
* Session close handler
*/
public function close() {
// Nothing
return true;
}
/**
* Session load handler. Load the session
* @param string Session ID
*/
public function read($session_id) {
// Load Table from the database
$dbTable = $this->dbOptions['db_table'];
$dbDataCol = $this->dbOptions['db_data_col'];
$dbIdCol = $this->dbOptions['db_id_col'];
// Load the session data from the database
$query = $this->pdo->prepare("
SELECT $dbDataCol
FROM $dbTable
WHERE $dbIdCol = :session_id");
$query->execute(array(':session_id' => $session_id));
return $query->fetchColumn();
}
/**
* Session save handler. Save the session
* @param string Session ID
* @param string Data to save to session
*/
public function write($session_id, $data) {
//load table form the database
$dbTable = $this->dbOptions['db_table'];
$dbDataCol = $this->dbOptions['db_data_col'];
$dbIdCol = $this->dbOptions['db_id_col'];
$dbTimeCol = $this->dbOptions['db_time_col'];
/* Try to update the existing session. If we can't find one, then create a new one. If you
* are using MySQL, this can be done in a single INSERT statment via INSERT ... ON
* DUPLICATE KEY UPDATE. Remove the UPDATE and edit the INSERT to do it this way.
* See http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
*
* This does two queries so you can use any DBMS.
*/
$query = $this->pdo->prepare("
UPDATE $dbTable
SET $dbDataCol = :data, last_activity = :last_activity
WHERE $dbIdCol = :session_id");
$query->execute(array(
":session_id" => $session_id,
":data" => $data,
"$dbTimeCol" => time()));
// No session to update? Create a new one
if ($query->rowCount() == 0) {
$query = $this->pdo
->prepare('
INSERT INTO sessions
(session_id, data, last_activity)
VALUES
(:session_id, :data, :last_activity)')
->execute(array(
':session_id' => $session_id,
':data' => $data,
'last_activity' => time())
);
}
}
/**
* Session delete handler. Delete the session from the database
* @param string Session ID
*/
public function destroy($session_id) {
//Load Table from the database
$dbTable = $this->dbOptions['db_table'];
$dbIdCol = $this->dbOptions['db_id_col'];
$this->pdo
->prepare("
DELETE FROM $dbTable
WHERE $dbIdCol = :session_id")
->execute(array(':session_id' => $session_id));
}
/**
* Session garbage collector. Delete any old expired sessions
* @param int How many seconds do sessions last for?
*/
public function gc($lifetime) {
//Load Table from the database
$dbTable = $this->dbOptions['db_table'];
$dbTimeCol = $this->dbOptions['db_time_col'];
$this->pdo
->prepare("
DELETE FROM $dbTable
WHERE $dbTimeCol < :min_time")
->execute(array(':min_time' => time() - $lifetime));
}
}
希望它能帮助其他人:Dcsrf保护在此起作用:
身份验证请求失败:无效的csrf令牌。
使用$session->isStarted()检查会话是否正确启动。
。顺便说一句,你清除了所有缓存和浏览器缓存吗?是的,我清除了所有缓存和浏览器缓存。。而且$session->isStarted()在我转储它时返回true。。。我还尝试禁用csrf令牌并使身份验证成功,但下一个问题是,当他在成功身份验证后转到主页时,主页会创建另一个会话(仅在PDOSessionHandler中,但在默认的sessionhandler中,它不会创建另一个会话)在这种情况下,令牌再次未经身份验证,并重定向我再次登录。因此,会话处理程序基本上不会拾取以前的会话,因此会为每个请求创建新的会话?基本上,这是我从它提供的日志中看到的。我将更新我的问题,以查看不带csrf令牌的完整日志。日志对此很清楚。每次新请求时都会再次创建会话。够了。你还改变了什么吗?比如重写会话处理程序?
framework:
session:
handler_id: session.handler.pdo
services:
pdo:
class: PDO
arguments:
dsn: "mysql:dbname=dev_reporting_system"
user: root
password: null
calls:
- [setAttribute, [3, 2]] # \PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION
session.handler.pdo:
class: foor\barBundle\Handler\CustomPdoSessionHandler
arguments: ["@pdo", "%pdo.db_options%"]