У меня есть класс UserMapper
<?php namespace Models; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use \PDO; class UserMapper implements UserProviderInterface { /** * Database connection. */ var $db = NULL; /** * Constructor function. Loads model from database if the id is known. * * @param $db * Database connection */ function __construct() { $this->db = ConnectionProvider::getConnection(); } function save(User $user) { $statement = $this->db->prepare('INSERT INTO user (username, password, salt, roles) VALUES (:username, :password, :salt, :roles)'); foreach (array('username', 'password', 'salt', 'roles') as $property) { $placeholders[':' . $property] = $user->get($property); } $isOk = $statement->execute($placeholders); return $isOk; } public function findByUsername($username) { $statement = $this->db->prepare('SELECT * FROM user WHERE username = :username'); $statement->execute(array(':username' => $username)); $data = $statement->fetch(PDO::FETCH_ASSOC); if($data['username'] == null) return null; else { $user = new User($data['username'], $data['salt'], $data['roles']); $user->set('password', $data['password']); return $user; } } function loadAll() { // Query for the existing users. $statement = $this->db->query('SELECT * FROM user'); $results = $statement->fetchAll(PDO::FETCH_ASSOC); // Format the list and output it as JSON. $data = array(); foreach ($results as $result) { $user = new User($result['username'], $result['salt'], $result['roles']); $user->set('passwort', $result['password']); $data[] = $user; } return $data; } /** * Delete this user. */ function delete(User $user) { if ($user->get('username')) { // Execute the delete query. $statement = $this->db->prepare('DELETE FROM user WHERE username = :username'); $statement->execute(array(':username' => $user->get('username'))); } } /// UserProviderInterface public function loadUserByUsername($username) { $user = $this->findByUsername($username); if($user == null) throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); return $user; } public function refreshUser(UserInterface $user) { if (!$user instanceof User) { throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); } return $this->loadUserByUsername($user->getUsername()); } public function supportsClass($class) { return $class === 'Models\User'; } }
и мой класс User
<?php namespace Models; use Symfony\Component\Security\Core\User\UserInterface; class User implements UserInterface{ var $username = NULL; var $password = NULL; var $salt = NULL; var $roles = NULL; function __construct($username, $password, $sal, $roles) { $this->username = $username; $this->password = $password; $this->salt = $salt; $this->roles = $roles; } function getUsername() { return $this->username; } function getRoles() { return $this->salt; } function getSalt() { return $this->roles; } function getPassword() { return $this->password; } function eraseCredentials() { } function get($property) { if (!empty($this->{$property})) { return $this->{$property}; } else { return false; } } function set($property, $value) { $this->{$property} = $value; } function getAll() { return array( 'username' => $this->get('username'), 'password' => $this->get('password'), 'salt' => $this->get('salt'), 'roles' => $this->get('roles') ); } }
И в моем index.php
я настраиваю контекст безопасности следующим образом:
$app['security.firewalls'] = array( 'secured' => array( 'pattern' => '^/', 'anonymous' => array(), 'form' => array( 'login_path' => 'login', 'check_path' => 'login_check' ), 'users' => $app->share(function () use ($app) { return $app['UserMapper']; }), ) ); $app['security.access_control'] = array( array('path' => '^/login', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'), array('path' => '^/', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'), array('path' => '^/comment', 'methode' => 'POST', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'), array('path' => '^/comment', 'methode' => 'DELETE', 'role' => 'ROLE_ADMIN'), array('path' => '^/location', 'methode' => 'GET, POST', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'), array('path' => '^/location', 'methode' => 'PUT, DELETE', 'role' => 'ROLE_ADMIN') ); $app['security.provider'] = array( 'users' => array( 'entity' => array('class' => 'Models\User', 'property' => 'username') ) ); $app['security.encoders'] = array( 'Models\User' => array( 'algorithm' => 'bcrypt', ) ); $app->register(new UrlGeneratorServiceProvider()); $app->register(new Silex\Provider\SecurityServiceProvider(), array( 'security.firewalls' => $app['security.firewalls'], 'security.access_control' => $app['security.access_control'], 'security.provider' => $app['security.provider'], 'security.encoders' => $app['security.encoders'], ));
Проблема заключается в том, что когда я отправляю форму для входа с паролем foo и паролем foo, которого нет в базе данных, контекст безопасности создает мне сеанс.
Что не так с поставщиком безопасности?
security.access_control
не определен в Silex\Provider\SecurityServiceProvider
. Я считаю, что это должно быть security.access_rules
:
$app['security.access_rules'] = array( array('^/admin', 'ROLE_ADMIN'), );