Symfony2 authentication (login) without doctrine?
I am new @symfony and completely new in doctrine. The symfony page contains a tutorial on how to create an sf2 login process. And I love it BUT I can't work with doctrine and I don't want to work with it (there are many thinkers who don't work with doctrine ... - like enum's etc.).
How I create a login controller, firewall setup, etc. is explained very well. BUT! I would like to create it without doctrine ... I have an existing database and I love simple sql. :-)
How can I use a simple sql in UserInterface ... that will work with inline input from sf2?
thanks a lot...
source to share
What you want to do is hook up your own UserProvider:
http://symfony.com/doc/current/cookbook/security/entity_provider.html
Instead of the Doctrine 2 Relational Object Manager (ORM), you can use the Doctrine 2 Database Access Layer (DBAL). It is a thin sql layer built on top of PDO. Has some helper procedures for sql creation.
http://symfony.com/doc/current/cookbook/doctrine/dbal.html
Of course, you can just use PDO directly:
http://symfony.com/doc/current/cookbook/configuration/pdo_session_storage.html
source to share
Here is the solution I propose in Symfony 3.0.
When I am implementing an existing postgresql database and I want to reuse a lot of existing PHP code, the ORM is not suitable for my case (too time consuming to reverse engineer). So I was actively looking for how to use Symfony without ORM . (I implemented DBAL because what I wrote for PDO works with it ... so far ... with some minor fixes).
Let's start: An important concept I needed to understand was taken from this page: http://symfony.com/doc/current/cookbook/security/custom_provider.html + everything about the security.yml file.
In the security file, it took me a while to realize that node providers only have two options of their own: "entity" or "memory" . And with "entity" one of them is bound to the ORM . So I realized that I needed to develop my own provider that will work with regular PDO .
Here is some of my code to give you an idea of how I finally did it, you will find the following files below:
- security.yml (There is probably room for improvement here, since I don't count too much on organizing the firewall part);
- CustomUsersProvider.php: a class that implements the UserProviderInterface interface (the PdoCustom class and its getUser () method is my own PDO preparation for fetching a user from my DB);
- services.yml: a service providing access to the CustomUsersProvider class and therefore providing access to the "provider" in the security file (if I checked it incorrectly), I pass the DBAL database configuration as an argument to the service so that it can be used in the instance my CustomUsersProvider object;
- CustomUsers.php: a class that acts as an object of my "custom_users" table to work with PDO fetching PDO :: FETCH_CLASS; it implements the Symfony interfaces: UserInterface and EquatableInterface;
- You still need to implement the Symfony Controller SecurityController (find it here: http://symfony.com/doc/2.0/book/security.html ) and its route to the / login and Twig file.
- You will probably notice when you read the code that $ email is used as $ username;
[project_name] \ application \ Config \ security.yml
encoders:
CustomBundle\Entity\CustomUsers:
algorithm: [enter an encoding algorithm, eg: MD5, sha512, etc.]
role_hierarchy:
ROLE_NAME2: ROLE_NAME1
ROLE_NAME3: ROLE_NAME2
providers:
custom_users_provider:
id: custom_users_provider
firewalls:
main_login:
pattern: ^/login$
anonymous: ~
main:
pattern: ^/
anonymous: true
provider: custom_users_provider
form_login:
check_path: /login_check
login_path: /login
provider: custom_users_provider
username_parameter: email
password_parameter: password
logout: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/secured_for_role_name, role: ROLE_NAME }
[project_name] \ CustomBundle \ Security \ CustomUsersProvider.php
<?php
namespace CustomBundle\Security;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use CustomBundle\DependencyInjection\PdoCustom;
use CustomBundle\Entity\CustomUsers;
class CustomUsersProvider implements UserProviderInterface
{
private $dbalConnection;
private $logger;
public function __construct($dbalConnection){
$this->dbalConnection = $dbalConnection;
////////////////EASTER EGG//////////////////////////
$this->logger = $GLOBALS['kernel']->getContainer()->get('logger');
$logger->info('EASTER EGG: YOU CAN ADD LOG THAT CAN BE FOUND UNDER [projectname]\var\logs\dev.log WHEN LAUNCHING THRU app_dev.php, WICH COULD BE USEFUL TOO');
////////////////////////////////////////////////////
}
public function loadUserByUsername($username)
{
$PdoCustom = new PdoCustom($this->dbalConnection);
$userData = $PdoCustom->getUser($username);
if ($userData) {
$password = $userData->password;
$salt = null;
$role = $userData->role;
$resToReturn = new CustomUsers();
$resToReturn->setCharact($username, $password, $role);
return $resToReturn;
}
throw new UsernameNotFoundException(
sprintf('Username "%s" does not exist.', $username)
);
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof CustomUsers) {
throw new UnsupportedUserException(
sprintf('Instances of "%s" are not supported.', get_class($user))
);
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === 'CustomBundle\Entity\CustomUsers';
}
}
?>
[project_name] \ SRC \ CustomBundle \ Ressources \ Config \ services.yml
custom_bundle.custom_users_provider.class : CustomBundle\Security\CustomUsersProvider
custom_users_provider:
class: %custom_bundle.custom_users_provider.class%
arguments: ["@doctrine.dbal.default_connection"]
[project_name] \ CustomBundle \ Entity \ CustomUsers.php
<?php
namespace CustomBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\EquatableInterface;
class CustomUsers implements UserInterface, EquatableInterface {
public $email;
public $password;
public $role;
public function __construct(){
}
public function setCharact($email,$password,$role){
$this->email = $email;
$this->password = $password;
$this->status = $status;
}
public function getRoles(){
return $this->role;
}
public function getPassword(){
return $this->password;
}
public function getSalt(){
return null;
}
public function getUsername(){
return $this->email;
}
public function eraseCredentials(){
}
public function isEqualTo(UserInterface $user)
{
if (!$user instanceof CustomUsers) {
return false;
}
if ($this->user_password !== $user->getPassword()) {
return false;
}
//if ($this->salt !== $user->getSalt()) {
// return false;
//}
if ($this->email !== $user->getUsername()) {
return false;
}
return true;
}
}
?>
So that it is, you still have a job to figure out all of this, but I hope this gives you directions that I find very hard to find on HOW TO USE SYMMETRY WITHOUT ORM :))
source to share