Я делаю REST API для моего приложения, управляемого JS.
Во время входа форма входа через AJAX отправляется на URL /rest/login
моего API.
Хотя я разделил брандмауэры для 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 при ошибке.
Мне удалось найти простое решение. Мне нужно было только написать класс, который реализует 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. Единственное, что я вижу, это поле «пароль», которое вы хотите сравнить, то же самое, что и в базе данных (с шифрованием), тогда я решил создать дополнительное поле только для этого использования.
Я надеюсь, что это поможет вам.
Привет