Подтвердить что ты не робот

Простая аутентификация ключа API в Symfony2 с использованием FOSUserBundle (и HWIOauthBundle), заполнение пробелов

Изменить: см. ниже мое собственное решение, которое на момент написания статьи функционирует, но несовершенно. Хотелось бы услышать критику и отзывы, если я получу что-то, что я чувствую, действительно твердо, тогда я сделаю запись в блоге для других людей, сталкивающихся с тем же вызовом.

Я боролся с этим в течение нескольких дней, и я надеюсь, что кто-то может сообщить мне, если я на правильном пути.

У меня есть система с веб-сервисом FOSRestBundle, в котором я в настоящее время использую FOSUserBundle и HWIOAuthBundle для аутентификации пользователей.

Я хотел бы настроить аутентификацию аутентификации apache для системы webservice.

Я прочитал http://symfony.com/doc/current/cookbook/security/api_key_authentication.html, и это кажется достаточно простым для реализации, я также установил UecodeApiKeyBundle, который, кажется, в основном просто реализация этой страницы книги.

Мой вопрос - это n00b... что теперь? На странице книги и в наборе оба документа проверяют подлинность пользователя по ключу API, но не затрагивают поток пользователей регистрации, генерируя ключи API, позволяя пользователям регистрироваться и т.д. Мне бы очень понравились простые конечные точки API для входа, регистрации и выхода из системы, которые могут использовать мои разработчики приложений. Что-то вроде /api/v 1/login и т.д.

Я думаю, что могу справиться с регистрацией.... логин меня сбивает с толку. Основываясь на некотором дополнительном чтении, мне кажется, что мне нужно сделать для входа в систему:

  • Создайте контроллер на api/v1/login, который принимает запросы POST. запрос будет выглядеть как {_username: foo, _password: bar} или что-то вроде {facebook_access_token: foo. Кроме того, для входа в facebook может потребоваться другое действие, например /user/login/facebook, и просто перенаправить на путь HWIOAuthBundle}.

  • Если запрос содержит параметры _username и _password, тогда я необходимо переслать запрос на регистрацию (я не уверен в этом один. Могу ли я просто обработать эту форму самостоятельно? Или, если я вручную проверю имя пользователя и пароль к базе данных?)

  • Добавить прослушиватель событий входа в систему, если пользователь успешно прошел аутентификацию, генерировать ключ api для пользователя (это необходимо, только если я не проверю его сам).

  • Верните API-ключ в ответ на запрос POST (это прерывает стратегия post-redirect-get, но в остальном я не вижу никаких проблем с этим) Я думаю, что это устраняет перенаправление на параметр проверки входа I перечисленных выше.

Как вы, наверное, видите, я в замешательстве. Это мой первый проект Symfony2, а книги на страницах "Безопасность" просты... но, похоже, замаскировали некоторые детали, и это оставило меня совершенно неуверенным в том, как продолжить.

Спасибо заранее!

=============================================== ==============

Edit:

Я установил аутентификацию ключа API в значительной степени идентично соответствующей статье поваренной книги: http://symfony.com/doc/current/cookbook/security/api_key_authentication.html

Чтобы обрабатывать вход пользователя в систему, я создал собственный метод контроллера. Я сомневаюсь, что это прекрасно, я бы хотел услышать некоторые отзывы о том, как это можно улучшить, но я верю, что я на правильном пути, так как мой поток теперь работает. Вот код (обратите внимание, что еще рано развиваться... Я еще не смотрел учетную запись в Facebook, только простой логин/пароль):

class SecurityController extends FOSRestController
{

    /**
     * Create a security token for the user
     */

    public function tokenCreateAction()
    {
        $request = $this->getRequest();

        $username = $request->get('username',NULL);
        $password = $request->get('password',NULL);

        if (!isset($username) || !isset($password)){
            throw new BadRequestHttpException("You must pass username and password fields");
        }

        $um = $this->get('fos_user.user_manager');
        $user = $um->findUserByUsernameOrEmail($username);

        if (!$user instanceof \Acme\UserBundle\Entity\User) {
            throw new AccessDeniedHttpException("No matching user account found");
        }

        $encoder_service = $this->get('security.encoder_factory');
        $encoder = $encoder_service->getEncoder($user);
        $encoded_pass = $encoder->encodePassword($password, $user->getSalt());

        if ($encoded_pass != $user->getPassword()) {
            throw new AccessDeniedHttpException("Password does not match password on record");
        }


        //User checks out, generate an api key
        $user->generateApiKey();
        $em = $this->getDoctrine()->getEntityManager();
        $em->persist($user);
        $em->flush();

        return array("apiKey" => $user->getApiKey());
    }

}

Это работает очень хорошо, и регистрация пользователя будет обрабатываться аналогичным образом.

Интересно, что метод аутентификации ключа api, который я реализовал из кулинарной книги, кажется, игнорирует параметры access_control в моем файле security.yml, в кулинарной книге они описывают, как генерировать токен только для определенного пути, но я не сделал этого, t как это решение, поэтому я внедрил свое собственное (а также немного плохое) решение, чтобы не проверять путь, который я использую для аутентификации пользователей

api_login:
    pattern: ^/api/v1/user/authenticate$
    security: false

api:
    pattern: ^/api/*
    stateless: true
    anonymous: true
    simple_preauth:
        authenticator: apikey_authenticator

Я уверен, что есть лучший способ сделать это тоже, но снова... не уверен, что это такое.

4b9b3361

Ответ 1

Я не думаю, что вам действительно нужна конечная точка /login.

В документе symfony клиент api должен передать его ключ (через параметр http apiKey) каждому запросу API.

Я не уверен в лучшей практике, но вы можете это сделать.

"The book page and bundle both cover authenticating a user by API key, but don't touch on the flow of logging users in, generating API keys, allowing users to register"

Лучше всего разрешить пользователям регистрироваться через веб-форму (например, с помощью маршрута fos_user_register). Пользовательский объект может иметь поле apikey, предварительно заполненное ключом, сгенерированным подобно этому sha1 (например, "secret".time()) и кнопку в своем профиле для восстановления ключа.

Ответ 2

Вы пытаетесь внедрить аутентификацию без сохранения имени пользователя и логин. Это в значительной степени то, что дает пропускная способность аутентификации Oauth2. Это довольно стандартно, поэтому вместо того, чтобы пытаться реализовать его самостоятельно, я бы рекомендовал вам использовать Bundle для этого, например FOSOauthServerBundle. Он может использовать FOSUserBundle в качестве своего поставщика услуг и будет более чистым, более защищенным и более простым в использовании, чем самодельное решение.

Чтобы зарегистрировать пользователя, вы можете создать действие регистра в вашем API (например, в REST API, я бы использовал POST-api/v1/users), а в методе контроллера копировать и проделывать код из FOSUserBundle: RegistrationController (конечно, адаптируйте его для ваших нужд).

Я сделал это в REST API, он работал как шарм.

Ответ 3

Class GenearteToken extends FOSRestController
{

     public getTokenAction(Request $request){

          $apiKey = $request->query->get('apikey');
          return $apiKey;
      }


}