Symfony 3 - 模式导致保护身份验证器的登录问题



我试图添加身份验证器,它应该只负责访问路径/Abc,默认情况下,其他安全区域由默认身份验证器保护。

只要我将模式线pattern: ^/Abc添加到我的 security.yml 中,一切正常。我可以登录和注销。用户通过身份验证令牌类 PostAuthenticationGuardToken 和 Firewall abc.

当我添加第 pattern: ^/Abc 行时,我无法再登录(进入/abc 区域)。提交登录表单应用程序后,重新加载到路径 login_abc

安全.yml

security:
   firewalls:
        # disables authentication for assets and the profiler, adapt it according to your needs
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        abc:
            anonymous: ~
            pattern: ^/Abc
            guard:
                authenticators:
                    - abc_authenticator
            form_login:
                login_path:     login_abc
                check_path:     login_abc
                remember_me:    false
            logout:
                path:   logout_abc
                target: main_index
        default:
            anonymous: ~
            pattern: ^/(?!Abc)
            form_login:
                always_use_default_target_path: false
                login_path:     login
                check_path:     login
                remember_me:    false
                logout:
                    path:   logout
                    target: main_index


   access_control:
            - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/login_abc, roles: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/Abc, roles: [ROLE_ABC] } 
            - { path: ^/Work, roles: [ROLE_WORK, ROLE_WORK2] }
            - { path: ^/Home, roles: [ROLE_HOME] }

abc身份验证器.php

namespace AppBundleSecurity;
use AppBundleEntityUser;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentRoutingRouterInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenTokenInterface;
use SymfonyComponentSecurityCoreExceptionAuthenticationException;
use SymfonyComponentSecurityCoreExceptionCustomUserMessageAuthenticationException;
use SymfonyComponentSecurityCoreExceptionUsernameNotFoundException;
use SymfonyComponentSecurityCoreUserUserInterface;
use SymfonyComponentSecurityCoreUserUserProviderInterface;
use SymfonyComponentSecurityGuardAbstractGuardAuthenticator;
use DoctrineBundleDoctrineBundleRegistry as Doctrine;

class abcAuthenticator extends AbstractGuardAuthenticator {
    const ACCESS_DENNIED = "Access dennied";
    /**
     * @var SymfonyComponentRoutingRouterInterface
     */
    private $router;
    /**
     * @var Doctrine
     */
    private $doctrine;

    /**
     * abcAuthenticator constructor.
     */
    public function __construct(RouterInterface $router, Doctrine $doctrine) {
        $this->router = $router;
        $this->doctrine = $doctrine;
    }
    public function start(Request $request, AuthenticationException $authException = null) {
        $url = $this->router->generate('login_abc');
        return new RedirectResponse($url);
    }
    public function getCredentials(Request $request) {
        if ($request->getPathInfo() != '/login_abc' || !$request->isMethod('POST')) {
            return;
        }
        return array(
            'cardToken' => $request->request->get('_cardToken'),
        );
    }
    public function getUser($credentials, UserProviderInterface $userProvider) {
        try {
            try {
                $user = $this->doctrine->getRepository(User::class)->findOneByCardToken($credentials['cardToken']);
                if (is_null($user)) {
                    throw new UsernameNotFoundException();
                }
                return $userProvider->loadUserByUsername($user->getUsername());
            } catch (UsernameNotFoundException $e) {
                throw new CustomUserMessageAuthenticationException(self::ACCESS_DENNIED);
            }
        }
        catch (UsernameNotFoundException $e) {
            throw new CustomUserMessageAuthenticationException(self::ACCESS_DENNIED);
        }
    }
    public function checkCredentials($credentials, UserInterface $user) {
        return true;
    }
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception) {
        $url = $this->router->generate('login_abc');
        return new RedirectResponse($url);
    }
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) {
        $url = $this->router->generate('abc_panel');
        return new RedirectResponse($url);
    }
    public function supportsRememberMe() {
        return false;
    }
}

身份验证器当然是注册为服务。

我不知道出了什么问题。请帮忙。

在您的getCredentials()方法中,您似乎只允许在转到 URL /login_abc(URL,而不是路由名称)时登录 - 但只允许在 URL 上运行防护/Abc .

使用多个防火墙很复杂 - 您可能会发现拥有单个防火墙然后允许运行多个身份验证更容易,直到您成功(基于 URL,然后是任何用户名、密码/令牌等),然后其余的将被跳过。

最新更新