【问题标题】:User and API Authentication via Token / Key通过令牌/密钥进行用户和 API 身份验证
【发布时间】:2014-12-17 01:04:39
【问题描述】:

我有一个使用 Symfony2 开发的服务器端 API,现在我尝试进行身份验证。

  1. 客户端/移动设备应用程序必须使用 API 密钥进行身份验证
  2. 使用该应用程序的用户必须使用电子邮件 + 密码进行身份验证并获得 access_token

因此我使用了这个防火墙和 apikey 验证器

firewalls:
    login:
        pattern:  ^/login$
        security: false

    secured_area:
        pattern: ^/
        stateless: true
        simple_preauth:
            authenticator: apikey_authenticator

API 密钥验证器

namespace Rental\APIBundle\Security;

use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;


class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface    {
    protected $userProvider;

    public function __construct(ApiKeyUserProvider $userProvider)
    {
        $this->userProvider = $userProvider;
    }

    public function createToken(Request $request, $providerKey)
    {

        //$apiKey = $request->query->get('apikey');
        // use test value
        $apiKey = "234234234";

        if (!$apiKey) {
            throw new BadCredentialsException('No API key found');
        }

        return new PreAuthenticatedToken(
            'anon.',
            $apiKey,
            $providerKey
        );
    }

    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
    {
        $apiKey = $token->getCredentials();
        $username = $this->userProvider->getUsernameForApiKey($apiKey);

        if (!$username) {
            throw new AuthenticationException(
                sprintf('API Key "%s" does not exist.', $apiKey)
            );
        }

        $user = $this->userProvider->loadUserByUsername($username);

        return new PreAuthenticatedToken(
            $user,
            $apiKey,
            $providerKey,
            $user->getRoles()
        );
    }

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

到目前为止,没问题。现在这个类使用下面类的方法

namespace Rental\APIBundle\Security;

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;

class ApiKeyUserProvider implements UserProviderInterface {
    public function getUsernameForApiKey($apiKey)
    {
        // Look up the username based on the token in the database
        // use test value
        $username = "Alex";

        return $username;
    }

    public function loadUserByUsername($username)
    {
        // return User by Username
    }

    public function refreshUser(UserInterface $user)
    {
        // code
    }

    public function supportsClass($class)
    {
        return 'Symfony\Component\Security\Core\User\User' === $class;
    }
}

我的详细问题是:

  1. 方法loadUserByUsername需要通过搜索用户名找到用户实体。但是从这个类我无法访问数据库。我找到了使用静态方法User::find() 的示例,但没有这样的方法,并且实体(MVC 的模型)也无法访问数据库。如何将用户从数据库中取出?
  2. 我想首先对 APP 本身进行身份验证以获取一般 API 访问权限,然后对用户进行身份验证以获取个人信息和有限的编辑权限。当用户通过电子邮件和密码登录时,数据已保存,例如在 UsernamePasswortToken 中,来自同一客户端的下一次呼叫如何使用 access_token 访问数据。会话对这些 AJAX HTTP 请求没有影响。

【问题讨论】:

    标签: php api rest symfony access-token


    【解决方案1】:

    1。 您应该为此使用依赖注入并在您的提供者中注入实体管理器。

     your_api_key_user_provider:
                class:     Rental\APIBundle\Security\ApiKeyUserProvider
                arguments: ["@doctrine.orm.entity_manager"]
     apikey_authenticator:
                class:     Rental\APIBundle\Security\ApiKeyAuthenticator
                arguments: [""@your_api_key_user_provider"]  
    

    然后将其添加到提供程序中:

        use Doctrine\ORM\EntityManager;
    
        class ApiKeyUserProvider implements UserProviderInterface {
    
            protected $em;
    
            public function __construct(EntityManager $em){
                $this->em = $entityManager;
            }
           //... Now you have access to database
    
        }
    

    2。 Ajax 可以发送 cookie,而 php 可以处理这些请求,就像普通的和使用会话一样。确定您的请求是否正在发送 cookie(请参阅 Why is jquery's .ajax() method not sending my session cookie?

    【讨论】:

      猜你喜欢
      • 2013-09-09
      • 2014-03-26
      • 1970-01-01
      • 2014-10-30
      • 2020-07-17
      • 2013-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多