Symfony 4-FOSUserBundle-保护身份验证器

时间:2018-07-30 14:37:23

标签: symfony fosuserbundle symfony4

我正在尝试在Symfony 4.1上实现带有保护的FOSUserBundle。 这是我的身份验证者:

<?php


namespace App\Security;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Http\Util\TargetPathTrait;

class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;

private $em;
private $router;
private $passwordEncoder;
private $csrfTokenManager;

public function __construct(EntityManagerInterface $em, RouterInterface $router, UserPasswordEncoderInterface $passwordEncoder, CsrfTokenManagerInterface $csrfTokenManager)
{
    $this->em = $em;
    $this->router = $router;
    $this->passwordEncoder = $passwordEncoder;
    $this->csrfTokenManager = $csrfTokenManager;
}

public function getCredentials(Request $request)
{
    $username = $request->request->get('_username');
    $password = $request->request->get('_password');
    $csrfToken = $request->request->get('_csrf_token');

    if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken('authenticate', $csrfToken))) {
        throw new InvalidCsrfTokenException('Invalid CSRF token.');
    }

    $request->getSession()->set(
        Security::LAST_USERNAME,
        $username
    );

    return [
        'username' => $username,
        'password' => $password,
    ];
}

public function getUser($credentials, UserProviderInterface $userProvider)
{
    $username = $credentials['username'];

    return $this->em->getRepository('App:User')
        ->findOneBy(['email' => $username]);
}

public function checkCredentials($credentials, UserInterface $user)
{
    $password = $credentials['password'];

    if ($this->passwordEncoder->isPasswordValid($user, $password)) {
        return true;
    }

    return false;
}

public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
    $targetPath = null;

    // if the user hit a secure page and start() was called, this was
    // the URL they were on, and probably where you want to redirect to
    $targetPath = $this->getTargetPath($request->getSession(), $providerKey);

    if (!$targetPath) {
        $targetPath = $this->router->generate('homepage');
    }

    return new RedirectResponse($targetPath);
}

protected function getLoginUrl()
{
    return $this->router->generate('fos_user_security_login');
}

/**
 * Does the authenticator support the given Request?
 *
 * If this returns false, the authenticator will be skipped.
 *
 * @param Request $request
 *
 * @return bool
 */
public function supports(Request $request)
{
    if($request->attributes->get('_route') !== 'fos_user_security_login'){
        return false;
    }
}
}

这是我的security.yaml文件:

security:
    encoders:
        App\Entity\User: bcrypt

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: ~
            logout: ~
            guard:
                authenticators:
                    - App\Security\LoginFormAuthenticator
#            form_login:
#               csrf_token_generator: security.csrf.token_manager
            remember_me:
                secret: '%env(APP_SECRET)%'

    access_control:
        # - { path: ^/admin, roles: ROLE_ADMIN }
        # - { path: ^/profile, roles: ROLE_USER }

还有fos_user.yaml:

fos_user:
    db_driver: 'orm'
    user_class: App\Entity\User
    firewall_name: main
    service:
        mailer: fos_user.mailer.twig_swift
    from_email:
        address: "admin@test.com"
        sender_name: "test"
    registration:
        form:
            type: App\Form\UserRegistrationFormType

每当我登录时,都会出现以下错误:

  

必须使用以下命令配置要由防火墙处理的检查路径   您的安全防火墙配置中的form_login。

我已经安装了安全捆绑包,并尝试通过官方文档中提供的步骤进行操作: https://symfony.com/doc/current/security/guard_authentication.html

我遵循了KnpUniversity上的教程,但这是针对Symfony 3的,看来事情不再以相同的方式起作用了。

肯定有我看不到的东西。

任何建议将不胜感激。

版本信息: -Symfony ^ 4.1 -FOSUserBundle ^ 2.1 -安全卫士^ 4.1

2 个答案:

答案 0 :(得分:0)

我认为这将帮助您更好地了解什么是symfony Guard和fos用户捆绑包。  Symfony Guard - You don't need FOSUserBundle

答案 1 :(得分:0)

提示:我有一个类似的问题。如果我没记错的话,您必须删除fos用户捆绑包路​​由中定义的登录页面的路由。我知道我模棱两可,但请检查路线。在使用Guard进行身份验证时,它正在寻找fosuser登录页面。