简体   繁体   中英

Symfony 2.6 Security Login redirects back to login page on successful login

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM