对于必须保持向后兼容性的authenticator类的方法

Before Symfony 2.8 SimplePreAuthenticatorInterface was in the following namespace Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface It have been deprecated in 2.8 and changed in 3.0 to Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface

now I'm writing a bundle which must work either in symfony 2.7 and symfony 3.0 it is an api authenticator bundle for a private use.

I would like to write a factory for it which checks interface existance

example from FosUserBundle

if (interface_exists('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')) {
    $tokenStorage = $this->get('security.token_storage');
} else {
    $tokenStorage = $this->get('security.context');
}

but my class which implements this interface is a service in DI and symfony firewall directly uses this.

My question is how could I make this abstraction in a manner of best practise and logical.

AccessTokenAuthenticator Class :

<?php

namespace MyCompany\SBundle\Security;
// this usage for before symfony 2.8
use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;

/**
 * Class AccessTokenAuthenticator
 */
class AccessTokenAuthenticator implements SimplePreAuthenticatorInterface
{

services.yml

# Authentication
mycompany_security.security.accesstoken_authenticator:
    class:     MyCompany\SBundle\Security\AccessTokenAuthenticator
    arguments: ["@mycompany_security.security.accesstoken_userprovider"]

Firewall Configuration :

secure_area:
    pattern:  ^/
    stateless: true
    simple_preauth:
        authenticator: mycompany_security.security.accesstoken_authenticator

My exact problem is even if I define two classes which are identical each other but the implementation namespace different even how could I give this to firewall ? How this can be abstracted from firewall ?

Any help would be appreciated.

OK I find the answer,

When I focus the service container and security.yml firewall configurations. I just forget, my firewall configuration can be different from symfony2 and symfony3 application.

In that manner I can would define a BaseAccessTokenAuthenticator and AccessTokenAuthenticator for either PreSymfony28 and Symfony30 and then I will put all the logic inside BaseAccessTokenAuthenticator and AccessTokenAuthenticator would be multiple and there would be 2 different service. One for symfony2.7 firewall configuration one for symfony3.0.

Base Class :

<?php

namespace MyCompany\SBundle\Security;

/**
 * Abstract Class BaseAccessTokenAuthenticator
 */
abstract class BaseAccessTokenAuthenticator
{
    public function createToken(Request $request, $providerKey)
    {
      // Implementation
    }

    public function authenticateToken(
        TokenInterface $token,
        UserProviderInterface $userProvider,
        $providerKey
    ) {
      // Implementation.
    }

    public function supportsToken(TokenInterface $token, $providerKey)
    {
      // Implementation.
    }
}

Symfony 3.0 class :

<?php

namespace MyCompany\SBundle\Security;

use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;

/**
 * Class AccessTokenAuthenticatorSf30
 */
class AccessTokenAuthenticatorSf30 extends BaseAccessTokenAuthenticator implements SimplePreAuthenticatorInterface
{
}

Pre Symfony 2.8 class :

<?php

namespace MyCompany\SBundle\Security;

use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;

/**
 * Class AccessTokenAuthenticatorPreSf28
 */
class AccessTokenAuthenticatorPreSf28 extends BaseAccessTokenAuthenticator implements SimplePreAuthenticatorInterface
{
}

Services :

# Authentication
mycompany.security.accesstoken_authenticator_pre_sf28:
    class:     MyCompany\SBundle\Security\AccessTokenAuthenticatorPreSf28
    arguments: ["@mycompany.security.accesstoken_userprovider"]

# Authentication
mycompany.security.accesstoken_authenticator_sf30:
    class:     MyCompany\SBundle\Security\AccessTokenAuthenticatorSf30
    arguments: ["@mycompany.security.accesstoken_userprovider"]

wide application firewall for symfony =< 2.8 :

    simple_preauth:
        authenticator: mycompany.security.accesstoken_authenticator_sf28

wide application firewall for symfony >= 2.8 :

    simple_preauth:
        authenticator: mycompany.security.accesstoken_authenticator_sf30

This is probably non-PSR compliant but will work (probably).

File AccessTokenAuthenticator.php

if (interface_exists('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')) {

    class AccessTokenAuthenticator implements \Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface { }

} else {
      class AccessTokenAuthenticator implements \Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface { }
}

Autoloading should still pick it up.