Приложение Symfony2 с аутентификацией RESTful, используя FOSRestBundle и FOSUserBundle

Я делаю REST API для своего приложения, управляемого JS.

Во время входа в систему форма входа выдается через AJAX для URL-адреса /rest/login в /rest/login моего API.

  • Если логин успешно завершен, он возвращает 204
  • Если он терпит неудачу, он возвращает 401

Хотя я разделял брандмауэры для API и самого приложения, они имеют один и тот же контекст, который должен означать, что когда пользователь аутентифицируется против API, он также аутентифицируется против приложения. Таким образом, когда сервер вернет 204, страница перезагрузится, и он должен перенаправить пользователя в приложение, потому что он теперь вошел в систему.

Я попытался использовать предварительно check_login страницу check_login для FOSUserBundle и указал /rest/login остался /rest/login там.

 login: path: /rest/login defaults: _controller: FOSUserBundle:Security:check methods: [ POST ] по login: path: /rest/login defaults: _controller: FOSUserBundle:Security:check methods: [ POST ] 

Это не работает, потому что он всегда возвращает перенаправление, несмотря ни на что. Я прочитал документацию для symfony и не смог найти, как создать пользовательскую страницу check_login . Мне нужно что-то вроде этого

 use Symfony\Component\Security\Core\Exception\AuthenticationException; use FOS\RestBundle\Controller\Annotations\View; class SecurityController { /** * @View(statusCode=204) */ public function loginAction($username, $password) { /* first I need to somehow authenticate user using normal authentication, that I've set up */ ... /* Then I need to return 204 or throw exception, based on result. This is done using FOSRestBundle and it's listeners. */ if(!$succesful) { throw new AuthenticationException(); } } } 

Я не знаю, как это сделать. Ничего, что я нашел в какой-либо документации, немного помогло мне. Я буду благодарен за любое предложение, которое укажет мне в правильном направлении.


EDIT: Чтобы еще больше упростить, к чему я стремлюсь. Я хочу, чтобы мой логин функционировал точно так же, как и обычный form_login . Я только хочу изменить ответ, который он отправляет обратно – вместо перенаправления я хочу 204 на успех и 401 при сбое.

Я смог найти простое решение. Мне нужно было написать класс, который реализует AuthenticationSuccessHandlerInterface и AuthenticationFailureHandlerInterface .

 use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; class AuthenticationRestHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface { public function onAuthenticationFailure(Request $request, AuthenticationException $exception) { return new Response('', Response::HTTP_UNAUTHORIZED); } public function onAuthenticationSuccess(Request $request, TokenInterface $token) { return new Response('', Response::HTTP_NO_CONTENT); } } 

Затем я зарегистрировал его как услугу и настроил как обработчики для брандмауэра.

 services: security.authentication_rest_handler: class: AuthenticationRestHandler security: firewalls: rest: pattern: ^rest context: app form_login: check_path: /rest/login provider: fos_userbundle failure_handler: inspireon.security.authentication_rest_handler success_handler: inspireon.security.authentication_rest_handler username_parameter: login password_parameter: password 

Проблема решена и не требуется сложный поставщик аутентификации 🙂

Я понял вашу проблему, потому что я прошел аналогичную ситуацию, но с SOAP-сервисами. В середине я мог повторно искать безопасность wsse, а Symfony2 уже предоставил решение

http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html

Он работает с реальным токеном, и вы можете совпадать с пользователем в FOSUserBundle. Единственное, что я вижу, это поле «пароль», которое вы хотите сравнить, такое же, как в базе данных (с шифрованием), тогда я решил создать дополнительное поле только для этого использования.

Надеюсь, это поможет вам.

Приветствую