Symfony2 扩展 DefaultAuthenticationSuccessHandler [英] Symfony2 extending DefaultAuthenticationSuccessHandler
问题描述
我想在身份验证成功后立即更改默认身份验证过程.我做了一个在认证成功之后和重定向之前调用的服务.
I want to alter default authentication process just after authentication success. I made a service that is called after authentication success and before redirect.
namespace PkrBlogUserBundleHandler;
use DoctrineORMEntityManager;
use PkrBlogUserBundleServiceEncoderWpTransitionalEncoder;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpKernelLogLoggerInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenTokenInterface;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationSuccessHandlerInterface;
use SymfonyComponentSecurityHttpAuthenticationResponse;
class AuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
{
protected $entityManager = null;
protected $logger = null;
protected $encoder = null;
public function __construct(EntityManager $entityManager, LoggerInterface $logger, WpTransitionalEncoder $encoder)
{
$this->entityManager = $entityManager;
$this->logger = $logger;
$this->encoder = $encoder;
}
/**
* This is called when an interactive authentication attempt succeeds. This
* is called by authentication listeners inheriting from
* AbstractAuthenticationListener.
*
* @param Request $request
* @param TokenInterface $token
*
* @return Response never null
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
$user = $token->getUser();
$newPass = $request->get('_password');
$user->setUserPassword($this->encoder->encodePassword($newPass, null));
$this->entityManager->persist($user);
$this->entityManager->flush();
//do redirect
}
}
在 services.yml 中
in services.yml
services:
pkr_blog_user.wp_transitional_encoder:
class: "%pkr_blog_user.wp_transitional_encoder.class%"
arguments:
cost: "%pkr_blog_user.wp_transitional_encoder.cost%"
logger: @logger
pkr_blog_user.login_success_handler:
class: PkrBlogUserBundleHandlerAuthenticationSuccessHandler
arguments:
entity_manager: @doctrine.orm.entity_manager
logger: @logger
encoder: @pkr_blog_user.wp_transitional_encoder
和 security.yml
and in security.yml
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: pkr_blog_admin_login
check_path: pkr_blog_admin_login_check
success_handler: pkr_blog_user.login_success_handler
logout:
path: pkr_blog_admin_logout
target: /
我想要实现的只是稍微改变默认行为,所以我想为什么不扩展 DefaultAuthenticationSuccessHandler
,向 onSuccessHandler()
添加一些东西并调用 parent::onSucessHandler()
.我试过了,但问题是我不知道如何将安全参数(在 security.yml 中设置)添加到我的扩展类构造函数中.DefaultAuthenticationSuccessHandler 使用 HttpUtils 和 $options 数组:
What I'm trying achieve is to just alter default behavior a little so I think why not to extend DefaultAuthenticationSuccessHandler
, add something to onSuccessHandler()
and call parent::onSucessHandler()
. I tried and the problem is that I have no clue how to add security parameters (set in security.yml) to my extended class constructor. DefaultAuthenticationSuccessHandler uses HttpUtils and $options array:
/**
* Constructor.
*
* @param HttpUtils $httpUtils
* @param array $options Options for processing a successful authentication attempt.
*/
public function __construct(HttpUtils $httpUtils, array $options)
{
$this->httpUtils = $httpUtils;
$this->options = array_merge(array(
'always_use_default_target_path' => false,
'default_target_path' => '/',
'login_path' => '/login',
'target_path_parameter' => '_target_path',
'use_referer' => false,
), $options);
}
所以我的扩展类构造函数应该是这样的:
So my extended class constructor should look like:
// class extends DefaultAuthenticationSuccessHandler
protected $entityManager = null;
protected $logger = null;
protected $encoder = null;
public function __construct(HttpUtils $httpUtils, array $options, EntityManager $entityManager, LoggerInterface $logger, WpTransitionalEncoder $encoder)
{
$this->entityManager = $entityManager;
$this->logger = $logger;
$this->encoder = $encoder;
}
将 HttpUtils 服务添加到我的 services.yml
中非常容易,但是如何使用 options 参数?
It's quite easy to add HttpUtils service to my services.yml
, but what with options argument?
services:
pkr_blog_user.wp_transitional_encoder:
class: "%pkr_blog_user.wp_transitional_encoder.class%"
arguments:
cost: "%pkr_blog_user.wp_transitional_encoder.cost%"
logger: @logger
pkr_blog_user.login_success_handler:
class: PkrBlogUserBundleHandlerAuthenticationSuccessHandler
arguments:
httputils: @security.http_utils
options: [] #WHAT TO ADD HERE ?
entity_manager: @doctrine.orm.entity_manager
logger: @logger
encoder: @pkr_blog_user.wp_transitional_encoder
推荐答案
如果您只为应用程序定义了一个成功/失败处理程序,则有一种稍微简单的方法来执行此操作.您可以覆盖 security.authentication.success_handler
和 security.authentication.failure_handler,而不是为
代替.success_handler
和 failure_handler
定义新服务
If you only have one success / failure handler defined for your application, there's a slightly easier way to do this. Rather than define a new service for the success_handler
and failure_handler
, you can override security.authentication.success_handler
and security.authentication.failure_handler
instead.
示例:
services.yml
services.yml
services:
security.authentication.success_handler:
class: StatSidekickUserBundleHandlerAuthenticationSuccessHandler
arguments: ["@security.http_utils", {}]
tags:
- { name: 'monolog.logger', channel: 'security' }
security.authentication.failure_handler:
class: StatSidekickUserBundleHandlerAuthenticationFailureHandler
arguments: ["@http_kernel", "@security.http_utils", {}, "@logger"]
tags:
- { name: 'monolog.logger', channel: 'security' }
AuthenticationSuccessHandler.php
AuthenticationSuccessHandler.php
<?php
namespace StatSidekickUserBundleHandler;
use SymfonyComponentHttpFoundationJsonResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentSecurityCoreAuthenticationTokenTokenInterface;
use SymfonyComponentSecurityHttpAuthenticationDefaultAuthenticationSuccessHandler;
use SymfonyComponentSecurityHttpHttpUtils;
class AuthenticationSuccessHandler extends DefaultAuthenticationSuccessHandler {
public function __construct( HttpUtils $httpUtils, array $options ) {
parent::__construct( $httpUtils, $options );
}
public function onAuthenticationSuccess( Request $request, TokenInterface $token ) {
if( $request->isXmlHttpRequest() ) {
$response = new JsonResponse( array( 'success' => true, 'username' => $token->getUsername() ) );
} else {
$response = parent::onAuthenticationSuccess( $request, $token );
}
return $response;
}
}
AuthenticationFailureHandler.php
AuthenticationFailureHandler.php
<?php
namespace StatSidekickUserBundleHandler;
use PsrLogLoggerInterface;
use SymfonyComponentHttpFoundationJsonResponse;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpKernelHttpKernelInterface;
use SymfonyComponentSecurityCoreExceptionAuthenticationException;
use SymfonyComponentSecurityHttpAuthenticationDefaultAuthenticationFailureHandler;
use SymfonyComponentSecurityHttpHttpUtils;
class AuthenticationFailureHandler extends DefaultAuthenticationFailureHandler {
public function __construct( HttpKernelInterface $httpKernel, HttpUtils $httpUtils, array $options, LoggerInterface $logger = null ) {
parent::__construct( $httpKernel, $httpUtils, $options, $logger );
}
public function onAuthenticationFailure( Request $request, AuthenticationException $exception ) {
if( $request->isXmlHttpRequest() ) {
$response = new JsonResponse( array( 'success' => false, 'message' => $exception->getMessage() ) );
} else {
$response = parent::onAuthenticationFailure( $request, $exception );
}
return $response;
}
}
就我而言,我只是想设置一些东西,以便在尝试使用 AJAX 进行身份验证时可以获得 JSON 响应,但原理是相同的.
In my case, I was just trying to set something up so that I could get a JSON response when I try to authenticate using AJAX, but the principle is the same.
这种方法的好处是无需任何额外工作,通常传递给默认处理程序的所有选项都应该被正确注入.这是因为 SecurityBundleDependencyInjectionSecurityFactory 在框架中的设置方式:
The benefit of this approach is that without any additional work, all of the options that are normally passed into the default handlers should get injected correctly. This happens because of how SecurityBundleDependencyInjectionSecurityFactory is setup in the framework:
protected function createAuthenticationSuccessHandler($container, $id, $config)
{
...
$successHandler = $container->setDefinition($successHandlerId, new DefinitionDecorator('security.authentication.success_handler'));
$successHandler->replaceArgument(1, array_intersect_key($config, $this->defaultSuccessHandlerOptions));
...
}
protected function createAuthenticationFailureHandler($container, $id, $config)
{
...
$failureHandler = $container->setDefinition($id, new DefinitionDecorator('security.authentication.failure_handler'));
$failureHandler->replaceArgument(2, array_intersect_key($config, $this->defaultFailureHandlerOptions));
...
}
它专门查找 security.authentication.success_handler
和 security.authentication.failure_handler
以便将配置中的选项合并到传入的数组中.我确定有一种方法可以为您自己的服务设置类似的东西,但我还没有研究过.
It specifically looks for security.authentication.success_handler
and security.authentication.failure_handler
in order to merge options from your config into the arrays passed in. I'm sure there's a way to setup something similar for your own service, but I haven't looked into it yet.
希望有所帮助.
这篇关于Symfony2 扩展 DefaultAuthenticationSuccessHandler的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!