如何在成功授权后返回 json 对象而不是重定向到默认路径?我使用的是Symfony 3.0.1,但我不使用FOSBundle。
我的登录控制器如下所示:
class ClientLoginController extends Controller
{
/**
* @Route("/login", name="login")
*/
public function loginAction(Request $request)
{
$client = new Client();
$form = $this->createForm(ClientLoginType::class, $client);
$form->handleRequest($request);
$authenticationUtils = $this->get('security.authentication_utils');
$lastEmail = $authenticationUtils->getLastUsername();
$error = $authenticationUtils->getLastAuthenticationError();
if ($form->isSubmitted() && $form->isValid())
{
return new JsonResponse(
array(
'message' => 'Success! You're authorised!',
'result' => $this->renderView('SymfonyBundle::client/success.html.twig')
), 200);
}
return $this->render(
'SymfonyBundle::security/security.html.twig',
array(
'login_form' => $form->createView(),
'error' => $error,
'last_email' => $lastEmail,
)
);
}
}
security.yml 配置中的登录部分如下所示:
form_login:
login_path: login
check_path: login
username_parameter: _email
failure_forward: false
default_target_path: login
csrf_token_generator: security.csrf.token_manager
提前谢谢你!
当您将登录表单发布到安全配置中设置为check_path
的URL时,symfony将拦截侦听器的请求并在内部处理用户身份验证,然后根据配置重定向到页面。因此,if ($form->isSubmitted() && $form->isValid())
中的代码实际上永远不会被调用。
您可以通过多种方式覆盖此行为:
- 创建身份验证侦听器,侦听
AuthenticationEvents::AUTHENTICATION_SUCCESS
和AuthenticationEvents::AUTHENTICATION_FAILURE
事件 - 创建身份验证处理程序
- 创建自定义身份验证系统
上面针对身份验证处理程序案例的链接博客文章正是您所需要的。我只是在这里复制粘贴代码,您可以在帖子中找到更多详细信息。
创建处理程序类:
// AuthenticationHandler.php
namespace path'to'your'class;
use Symfony'Component'HttpFoundation'Response;
use Symfony'Component'HttpFoundation'RedirectResponse;
use Symfony'Component'Routing'RouterInterface;
use Symfony'Component'HttpFoundation'Session'Session;
use Symfony'Component'Security'Core'Authentication'Token'TokenInterface;
use Symfony'Component'Security'Core'Exception'AuthenticationException;
use Symfony'Component'HttpFoundation'Request;
use Symfony'Component'Security'Core'SecurityContextInterface;
use Symfony'Component'Security'Http'Authentication'AuthenticationSuccessHandlerInterface;
use Symfony'Component'Security'Http'Authentication'AuthenticationFailureHandlerInterface;
class AuthenticationHandler implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface
{
private $router;
private $session;
/**
* Constructor
*
* @author Joe Sexton <joe@webtipblog.com>
* @param RouterInterface $router
* @param Session $session
*/
public function __construct( RouterInterface $router, Session $session )
{
$this->router = $router;
$this->session = $session;
}
/**
* onAuthenticationSuccess
*
* @author Joe Sexton <joe@webtipblog.com>
* @param Request $request
* @param TokenInterface $token
* @return Response
*/
public function onAuthenticationSuccess( Request $request, TokenInterface $token )
{
// if AJAX login
if ( $request->isXmlHttpRequest() ) {
$array = array( 'success' => true ); // data to return via JSON
$response = new Response( json_encode( $array ) );
$response->headers->set( 'Content-Type', 'application/json' );
return $response;
// if form login
} else {
if ( $this->session->get('_security.main.target_path' ) ) {
$url = $this->session->get( '_security.main.target_path' );
} else {
$url = $this->router->generate( 'home_page' );
} // end if
return new RedirectResponse( $url );
}
}
/**
* onAuthenticationFailure
*
* @author Joe Sexton <joe@webtipblog.com>
* @param Request $request
* @param AuthenticationException $exception
* @return Response
*/
public function onAuthenticationFailure( Request $request, AuthenticationException $exception )
{
// if AJAX login
if ( $request->isXmlHttpRequest() ) {
$array = array( 'success' => false, 'message' => $exception->getMessage() ); // data to return via JSON
$response = new Response( json_encode( $array ) );
$response->headers->set( 'Content-Type', 'application/json' );
return $response;
// if form login
} else {
// set authentication exception to session
$request->getSession()->set(SecurityContextInterface::AUTHENTICATION_ERROR, $exception);
return new RedirectResponse( $this->router->generate( 'login_route' ) );
}
}
}
将其注册为服务,并设置为所用防火墙的成功和失败处理程序:
# Resources/config/services.yml
acme.security.authentication_handler:
class: path'to'your'class'AuthenticationHandler
public: false
arguments:
- @router
- @session
# app/config/security.yml
security:
firewalls:
main:
form_login:
check_path: security_check_route
success_handler: acme.security.authentication_handler
failure_handler: acme.security.authentication_handler