I am currently setting up a login system with a custom User Provider for Symfony2. I made the User and Provider classes, and the login system works fine with "manual" test variables. For example, this is my provider with test user data that always has a successful login:
<?php
namespace SoftAltern\DashboardBundle\Security\User;
use Symfony\Component\HttpFoundation\Request;
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;
class WebserviceUserProvider implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$userData = [
'username' => 'test',
'password' => 'testpass',
'roles' => [],
];
if ($userData) {
return new WebserviceUser($userData['username'], $userData['password'], '', $userData['roles']);
}
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))
);
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === 'SoftAltern\DashboardBundle\Security\User\WebserviceUser';
}
}
This works fine obviously. However, when I try adding my own check that returns an array built in the same format, it just goes back to the login page. Here is that example:
<?php
namespace SoftAltern\DashboardBundle\Security\User;
use Symfony\Component\HttpFoundation\Request;
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 SoftAltern\DashboardBundle\Helper\I5ToolkitHelper;
class WebserviceUserProvider implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$request = Request::createFromGlobals();
$toolkit = new I5ToolkitHelper;
$userData = $toolkit->checkUserData($username, $request->request->get('_password'));
if ($userData) {
return new WebserviceUser($userData['username'], $userData['password'], '', $userData['roles']);
}
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))
);
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === 'SoftAltern\DashboardBundle\Security\User\WebserviceUser';
}
}
I believe that the issue lies in using the request to get the password. However, in my current system (an AS/400 IBM iSeries), there is no way to just grab the password based on the username. So what I'm trying to do is use the i5ToolKit, check the credentials, and return the userData
based on a successful iSeries login or not. It returns the array fine, but still just redirects back to the login page on success.
The reason I believe it has something to do with the request is because if I comment that part out and manually submit a valid username and password to my I5ToolKitHelper
, everything works as expected.
I have also already tried the way they suggested using request
in this post , but it didn't help either.
Here is my security.yml
:
# you can read more about security in the related section of the documentation
# http://symfony.com/doc/current/book/security.html
security:
# http://symfony.com/doc/current/book/security.html#encoding-the-user-s-password
encoders:
SoftAltern\DashboardBundle\Security\User\WebserviceUser: 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:
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
# the login page has to be accessible for everybody
login:
pattern: ^/login$
security: false
# secures part of the application
soft_altern_dashboard_secured_area:
pattern: ^/
# it's important to notice that in this case _demo_security_check and _demo_login
# are route names and that they are specified in the AcmeDemoBundle
form_login:
check_path: soft_altern_dashboard_login_check
login_path: soft_altern_dashboard_login
logout:
path: soft_altern_dashboard_logout
target: soft_altern_dashboard_homepage
#anonymous: ~
#http_basic:
# realm: "Secured Demo Area"
# with these settings you can restrict or allow access for different parts
# of your application based on roles, ip, host or methods
# http://symfony.com/doc/current/cookbook/security/access_control.html
access_control:
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
Any help would be greatly appreciated!
Edit : I error logged the password during one login and it looks like it hits the login check twice, and on the second go around the password is empty. This behavior might be for security reasons. I'm not sure if I have a setting wrong that might be causing this.
There could be a number of related things. The page that Symfony redirects to is normally stored into session. You can change it. But first, try to add under the form_login setting the following option:
form_login:
#...
use_referer: true
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.