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

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

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

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

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

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

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();
}
}
}

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


РЕДАКТИРОВАТЬ: Чтобы еще больше упростить то, к чему я стремлюсь. Я хочу, чтобы мой логин функционировал точно так же, как обычно form_login. Я только хочу изменить ответ, который он отправляет обратно — вместо перенаправления я хочу 204 при успехе и 401 при ошибке.

5

Решение

Мне удалось найти простое решение. Мне нужно было только написать класс, который реализует 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

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

12

Другие решения

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

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

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

Я надеюсь, что это поможет вам.

Привет

1

По вопросам рекламы [email protected]