Symfony 2 项目中的双向认证

Posted

技术标签:

【中文标题】Symfony 2 项目中的双向认证【英文标题】:Two-way authentication in Symfony 2 project 【发布时间】:2014-07-26 19:15:20 【问题描述】:

我需要根据这个算法在我的一个 Symfony 2 项目中实现双向身份验证过程:

    用户在身份验证表单中输入他的用户名和密码并提交。 系统首先检查他的用户名和密码默认方式(所有用户都使用Doctrine ORM存储)。 如果上一步失败,调用外部 API 并将用户名和 md5(password) 传递给它。 如果上一步成功,则创建一个新的用户实体并将其用作经过身份验证的用户。 如果步骤 #3 失败,则认为身份验证失败。

我已经有一个服务可以调用,通过用户名和密码使用外部 API 对用户进行身份验证,我只是在寻找一种在身份验证过程中使用它的方法。

实现此行为的最简单方法是什么?我只需要指出正确的方向。

更新

实施“custom authenticator”是解决这个问题的好方法吗?还是有更好的方法?

查看文档,我将不得不在我的自定义身份验证器中实现两个身份验证步骤。是否可以只实施额外的步骤?

【问题讨论】:

看看github.com/scheb/two-factor-bundle 看看:先symfony.com/doc/current/cookbook/security/…;第二个symfony.com/doc/current/book/… 您可能还需要了解 Symfony 中的自定义提供程序和服务,因此您需要查看 1) symfony.com/doc/current/cookbook/security/entity_provider.html 和 2) symfony.com/doc/current/book/service_container.html 【参考方案1】:

是的,这就是要走的路。如果您的网络服务可以仅通过用户名为您提供用户,那么您只能在 UserProvider 中执行此操作,因为在它的范围内您只有用户名。如果您必须通过 un/pw 进行查询,那么您必须在身份验证器中进行查询,因为在该范围内您有密码。所以,用简单的形式,它看起来像这样

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) 

        return new UsernamePasswordToken(
            $user,
            $user->getPassword(),
            $providerKey,
            $user->getRoles()
        );
    

    // remote users fallback

    $webUser = $this->externalUserService->getByUsernamePassword(
        $token->getUsername(),
        $token->getCredentials()

    );

    if ($webUser) 
        return new UsernamePasswordToken(
            $webUser,
            $token->getCredentials(),
            $providerKey,
            $webUser->getRoles()
        );
    

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

Ofc 在这个类中有太多的 if,它负责不止一件事,所以为了整洁,您可以应用复合模式并拥有 3 个身份验证器、一个通用复合材料、第二个本地数据库身份验证器和第三个外部服务身份验证器,以及像这样从服务配置构建它。

# services.yml

my_app.authenticator.main:
    class: MyApp/Security/Core/Authentication/CompisiteAuthenticator
    calls:
        - [ add, [@my_app.authenticator.locale]]
        - [ add, [@my_app.authenticator.remote]]

my_app.authenticator.locale:
    class: MyApp/Security/Core/Authentication/LocalAuthenticator
    arguments: [@security.encoder_factory]

my_app.authenticator.remote:
    class: MyApp/Security/Core/Authentication/RemoteAuthenticator
    arguments: [@my_app.remote_user_service]

复合

<?php

namespace MyApp/Security/Core/;

class CompositeAuthenticator implements SimpleFormAuthenticatorInterface

    /** @var SimpleFormAuthenticatorInterface[] */
    protected $children = array();

    public function add(SimpleFormAuthenticatorInterface $authenticator)
    
        $this->children[] = $authenticator;
    

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

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

    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
    
        $result = null;
        foreach ($this->children as $authenticator)
        
            $result = $authenticator->authenticateToken($token, $userProvider, $providerKey);
            if ($result) 

                return $result;
            
        

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

我想现在本地和远程身份验证器是微不足道的

【讨论】:

以上是关于Symfony 2 项目中的双向认证的主要内容,如果未能解决你的问题,请参考以下文章

将http的web项目改成https双向认证保护证书生成

SSL双向认证和单向认证的区别是啥?

TOMCAT配置HTTPS双向认证,为啥始终无法访问

密码学ssl双向认证和单向认证原理

不是很明白ssl双向认证和单向认证有啥区别吗?

nginx 正向代理 配置https 双向认证