簡體   English   中英

使用simple_form身份驗證器的Symfony2 + FOS

[英]Symfony2 + FOS using simple_form authenticator

我使用FriendsOfSymfony UserBundle 當我將防火牆中的所有內容都設置為form_login ,它可以工作,但是如果我將其設置為simple_form以使用Custom Authenticator,那么即使帳戶被鎖定或禁用,也讓我登錄。 我想檢查用戶是否來自正確的IP,這就是為什么我創建了自定義身份驗證器,但是似乎某些來自FOS的身份驗證沒有以這種方式處理。 如何在仍保留FOS UserBundle的全部功能的同時,將simple_form與自定義身份驗證simple_form一起使用?

除了標准以外,還有其他方法可以實現其他身份驗證嗎? 也許我做錯了什么? 我知道我可以更正身份驗證器的此代碼以檢查是否已鎖定/啟用等,但我認為-因為它實際上已經在FOS中完成-為什么我應該這樣做?

編輯:另外,我注意到當我使用simple_form ,不會調用Symfony\\Component\\Security\\Core\\User\\UserChecker類的方法。

以下是我的authenticator和security.yml代碼:

config.yml

services:
    login_authenticator:
        class:     Forex\AlchemyBundle\Security\LoginAuthenticator
        arguments: ["@security.encoder_factory"]

security.yml

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email

    firewalls:
        main:
            pattern: ^/
            simple_form:
                authenticator: login_authenticator
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            logout:       true
            anonymous:    true

    access_control:
        - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } # To be removed
        - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/, role: ROLE_ADMIN }
        - { path: ^/.*, roles: ROLE_USER }

LoginAuthenticator

<?php

namespace Forex\AlchemyBundle\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class LoginAuthenticator implements SimpleFormAuthenticatorInterface
{
    private $encoderFactory;

    public function __construct(EncoderFactoryInterface $encoderFactory)
    {
        $this->encoderFactory = $encoderFactory;
    }

    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
    {
        try {
            $user = $userProvider->loadUserByUsername($token->getUsername());
        } catch (UsernameNotFoundException $e) {
            throw new AuthenticationException('Invalid username or password');
        }

        $encoder = $this->encoderFactory->getEncoder($user);
        $passwordValid = $encoder->isPasswordValid(
            $user->getPassword(),
            $token->getCredentials(),
            $user->getSalt()
        );

        if ($passwordValid) {

            $request = Request::createFromGlobals();

            $current_ip = $request->server->get('REMOTE_ADDR');

            $user->setLoggedIP($current_ip);

            if (!$user->isValidIP()) {
                throw new AuthenticationException(
                    "You cannot login from your location.",
                    100
                );
            }

            return new UsernamePasswordToken(
                $user,
                $user->getPassword(),
                $providerKey,
                $user->getRoles()
            );
        } else {
            // TODO: Check if there weren't too many tries to login
        }

        throw new AuthenticationException('Invalid username or password');
    }

    public function supportsToken(TokenInterface $token, $providerKey)
    {
        return $token instanceof UsernamePasswordToken
            && $token->getProviderKey() === $providerKey;
    }

    public function createToken(Request $request, $username, $password, $providerKey)
    {
        return new UsernamePasswordToken($username, $password, $providerKey);
    }

}

我面臨着同樣的問題。 這是我解決的方法。

您必須從Authenticator中的authenticateToken()方法中調用UserChecker類的checkPreAuth()和checkPostAuth()方法。

這樣可以完成:

1)配置user_checker服務:

services:
    app.user_checker:
        class: AppBundle\Security\UserChecker

2)將autenticator配置為服務並注入user_checker服務:

services:
    app.my_authenticator:
        class:     AppBundle\Security\MyAuthenticator
        arguments: ["@app.user_checker", "@security.password_encoder"]

3)現在您可以在authenticateToken()上調用checkPreAuth()和checkPostAuth()

無論如何,我認為symfony方法是正確的方法,因為在我的情況下,y需要在simple_form中執行與login_form不同的檢查。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM