简体   繁体   中英

Additional security checks on Symfony login

I'm using symfony 2.5 and I've come across a roadblock.

I am using SecurityContext as per symfony documentation in order to authenticate users. Specifically I currently have:

$securityContext = $this->container->get('security.context');

# If authenticated through Symfony
if ($securityContext->isGranted('IS_AUTHENTICATED_FULLY'))
{
    return $this->redirect($this->generateUrl('accounts_dashboard'), 301);

}
.....

This works well but this application registers users from several locations and at the time we didn't control duplicate registrations. This means we have multiple entries for the same email address.

Because of this, when someone tries to login and there are several accounts under the same email address the login procedure fails because it is selecting the wrong account.

I have other fields in the database that I could use to match the correct accounts, like active status, last login IP or even the last login date. The issue I have is that I am uncertain how to create additional checks during login to validate that information properly.

What would be the correct approach without having to rework the entire login logistics so that I could do additional checks on the database for the provided email address before calling SecurityContext and the rest of the login procedure? Essentially I am just trying to do additional checks after the login for has been submitted to ensure the correct account is being selected instead of the first match in the database.

You need to implement a custom UserProvider. Example:

<?php
namespace Acme\Security\Authorization;


use Symfony\Bridge\Doctrine\Security\User\EntityUserProvider;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;

class MyCustomEmailUserProvider extends EntityUserProvider
{

    /**
     * {@inheritdoc}
     */
    public function loadUserByUsername($username)
    {

        //your code to get user by email goes here
        // if you found User, you need to return it from this method, otherwise throw an exception

        throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username));
    }
}

You don't have to extend EntityUserProvider , you may consider your own UserProviderInterface implementation.

Register it as a service (assuming security.my_custom_email_user_provider service name), add your required dependencies and then add it to security.yml :

providers:
    main:
        id: security.my_custom_email_user_provider

And then use this provider on your login form:

firewalls:
      firewall_name:
            form_login:
                 provider: main

Check out Cookbook article for additional information.

UserProvider should return user by username, nothing else, it should not do some heavy logic. I think you can try to create your own authenticator as explained here by implementing the SimpleFormAuthenticatorInterface interface.

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