Symfony2 扩展 DefaultAuthenticationSuccessHandler [英] Symfony2 extending DefaultAuthenticationSuccessHandler

查看:22
本文介绍了Symfony2 扩展 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_handlersecurity.authentication.failure_handler,而不是为 success_handlerfailure_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_handlersecurity.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆