Symfony 安全配置,check_path 转到定义的控制器

Symfony security configuration, check_path goes to defined controller

我是 symfony 的新手,我正在尝试创建自己的身份验证。 (我有外部身份验证系统,所以我声明了我的用户 class 和 UserProvider) 我已经配置了一些路由、控制器和安全 yml,但是当我发送登录表单时,我最终遇到错误

Full authentication is required to access this resource.

这是我的安全配置:

security:
encoders:
    App\Domain\User\ValueObject\User: bcrypt
providers:
    UserProvider:
        id: App\Providers\UserProvider

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    login:
        pattern: ^/login
        anonymous: ~
    login_others:
        pattern: ^/login/.*$
        anonymous: ~
    register:
        pattern: ^/register.*$
        anonymous: ~
    bye:
        pattern: ^/bye
        anonymous: ~
    main:
        provider: UserProvider
        pattern: ^/.*
        form_login:
            # submit the login form here
            check_path: user.login.check

            # the user is redirected here when they need to log in
            login_path: /login
        logout:
            path:   /logout
            target: /login
            invalidate_session: false

# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
     - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
     - { path: ^/login/.*$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
     - { path: ^/register.*$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
     - { path: ^/bye$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
     - { path: ^/.+$, roles: ROLE_USER }

我的路由控制器如下所示:

    class LoginController extends Controller
{
    /**
     * @param AuthenticationUtils $authUtils
     * @param TokenStorageInterface $tokenStorage
     * @return Response
     *
     * @Route("/login", name="user.login", methods="GET")
     */
    public function loginAction(
        AuthenticationUtils $authUtils,
        TokenStorageInterface $tokenStorage
    ) {
        if (!is_null($tokenStorage->getToken()) && in_array('ROLE_USER', $tokenStorage->getToken()->getRoles())) {
            return $this->redirect($this->generateUrl('dashboard'));
        }

        $error = $authUtils->getLastAuthenticationError();
        $lastUsername = $authUtils->getLastUsername();

        return $this->render('user/login.twig', [
            'error'         => $error,
            'last_username' => $lastUsername,
        ]);
    }

    /**
     *
     * @Route("/login_check", name="user.login.check", methods={"POST"})
     */
    public function loginCheckAction()
    {

    }

知道我做错了什么吗?我几乎可以肯定这是配置问题,但似乎我不明白它。

这里是一个简单的配置:

#config/packages/security.yaml
# ...
providers:
    user_provider:
        entity:
            class: App\Providers\UserProvider
firewalls:    
    main:
        anonymous: ~
        form_login:
            login_path: login
            check_path: login
        logout:
            path: /logout
            target: /
access_control:
    - { path: dashboard, roles: ROLE_USER }

登录控制器

/**
 * @Route("/login", name="login")
 */
public function login(Request $request, AuthenticationUtils $authenticationUtils)
{
    $error = $authenticationUtils->getLastAuthenticationError();

    $lastUsername = $authenticationUtils->getLastUsername();

    return $this->render('login.html.twig', array(
        'last_username' => $lastUsername,
        'error'         => $error,
    ));
}

然后您可以在登录后设置默认重定向:

#config/packages/security.yaml
security:
    # ...
    firewalls:
        main:
            form_login:
                # ...
                default_target_path: dashboard

希望对您有所帮助

我终于想出了更多的工作配置

security:
    encoders:
        App\Domain\User\ValueObject\User: bcrypt
    providers:
        UserProvider:
            id: App\Security\UserProvider

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: ~
            provider: UserProvider
            pattern: ^/.*
            form_login:
                login_path: user.login
            logout:
                path:   /logout
                target: user.login
                invalidate_session: false

    # Easy way to control access for large sections of your site
    # Note: Only the *first* access control that matches will be used
    access_control:
         - { path: ^/login.*$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
         - { path: ^/register.*$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
         - { path: ^/.+$, roles: ROLE_USER }

如您所见,我没有为我的 form_login 配置检查路径。那是因为它不想为登录的用户替换匿名用户令牌,所以我最终创建了自己的登录检查端点并手动完成,如下所示:

/**
 * @param Request $request
 * @param PasswordAuthenticator $authenticator
 * @param UserProvider $provider
 * @param Session $session
 * @param TokenStorageInterface $storage
 * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
 *
 * @Route("/login/check", name="user.login.check", methods={"POST"})
 */
public function checkLoginUser(
    Request $request,
    PasswordAuthenticator $authenticator,
    UserProvider $provider,
    Session $session,
    TokenStorageInterface $storage
) {
    $token = $authenticator->createToken(
        $request,
        $request->request->get('_username'),
        $request->request->get('_password'),
        'UserProvider'
    );

    $authenticator->supportsToken($token, 'UserProvider');
    try {
        $newToken = $authenticator->authenticateToken($token, $provider, $token->getUser());

        $storage->setToken($newToken);
        $session->set('_security_main', serialize($newToken));

        return $this->redirect($this->generateUrl('dashboard'));
    } catch (CustomUserMessageAuthenticationException $e) {
        $error = $e->getMessage();
    }

    return $this->render('user/login.twig', [
        'error'         => $error,
        'last_username' => $request->request->get('_username'),
    ]);

}