I'm trying to create a custom connection where I should use web service. So I read the tutorial on security and this one on custom provider. Now I'm trying to create my own login form with 3 fields : Email, password and number. After validation I understood that my /login_check
pass in the function loadUserByUsername($username)
, but this function took in argument just $username
and doesn't take my fields email and number. To execute my web service I need to get my 3 args. How can I customize my login form?
The goal is: When users submit the login form I want to send a web service with login form args. If I get my response without error I want to connect my user loaded by web service to symfony2 toolbar else I want to display an error message.
You can see my code here :
Security.yml :
security:
encoders:
MonApp\MonBundle\Security\User\WebserviceUser: sha512
#Symfony\Component\Security\Core\User\User: plaintext
# http://symfony.com/doc/current/book/security.html#hierarchical-roles
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
# http://symfony.com/doc/current/book/security.html#where-do-users-come- from-user-providers
providers:
#in_memory:
#memory:
#users:
#ryan: { password: ryanpass, roles: 'ROLE_USER' }
#admin: { password: kitten, roles: 'ROLE_ADMIN' }
webservice:
id: webservice_user_provider
# the main part of the security, where you can set up firewalls
# for specific sections of your app
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
area_secured:
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
default_target_path: /test
logout:
path: /logout
target: /
# with these settings you can restrict or allow access for different parts
# of your application based on roles, ip, host or methods
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_AUTHENTICATED }
WebserviceUser.php :
<?php
namespace MonApp\MonBundle\Security\User;
use Symfony\Component\Security\Core\User\UserInterface;
class WebserviceUser implements UserInterface
{
private $email;
private $password;
private $num;
private $salt;
private $roles;
public function __construct($email, $password, $num, $salt, array $roles)
{
$this->email = $email;
$this->password = $password;
$this->num = $num;
$this->salt = $salt;
$this->roles = $roles;
}
public function getUsername()
{
return '';
}
public function getEmail()
{
return $this->email;
}
public function getPassword()
{
return $this->password;
}
public function getNum()
{
return $this->num;
}
public function getSalt()
{
return $this->salt;
}
public function getRoles()
{
return $this->roles;
}
public function eraseCredentials()
{}
public function isEqualTo(UserInterface $user)
{
if (!$user instanceof WebserviceUser) {
return false;
}
if ($this->email !== $user->getEmail()) {
return false;
}
if ($this->password !== $user->getPassword()) {
return false;
}
if ($this->num !== $user->getNum()) {
return false;
}
if ($this->getSalt() !== $user->getSalt()) {
return false;
}
return true;
}
}
WebserviceUserProvider.php
<?php
namespace MonApp\MonBundle\Security\User;
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 MonApp\MonBundle\Security\User\WebserviceUser;
class WebserviceUserProvider implements UserProviderInterface
{
public function loadUserByUsername($username)
{
//print_r($username);
//die();
// effectuez un appel à votre service web ici
return new WebserviceUser('email', 'password', '45555', 'salt', array('ROLE_USER'));
//throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof WebserviceUser) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
}
print_r($user);
die();
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === 'MonApp\MonBundle\Security\User\WebserviceUser';
}
}
service.yml
parameters:
webservice_user_provider.class: MonApp\MonBundle\Security\User\WebserviceUserProvider
services:
webservice_user_provider:
class: "%webservice_user_provider.class%"
I won't put all the code, but my login action, template and routing are exactly the same than security link. But my user new WebserviceUser('email', 'password', '45555', 'salt', array('ROLE_USER'))
isn't connected to the toolbar. So I think I forgot something...
Do I need to use a Listener, UserToken and Factory to do that ?
Ok boy, prepare for a long answer.
I assume that you have a folder named
Security
placed in/MonApp/MonBundle
First you need a custom Token placed in
Security/Token/WebServiceToken
Then you need a Firewall in
Security/Authentication/WebServiceAuthenticationListener
Then you need an Authentication provider in
Security/Authentication/WebServiceAuthenticationProvider
Now the factory ...
Security/Factory/WebServiceFactory
You have to edit WebServiceUserProvider by adding this function
And remove $roles from you WebServiceUSer class:
Ok, now you have all you security classes done. Let's configure this....
In the class
MonBundle
In the config of
MonBundle
And last, in your app config: