Symfony2的延长DefaultAuthenticationSuccessHandler [英] Symfony2 extending DefaultAuthenticationSuccessHandler

查看:230
本文介绍了Symfony2的延长DefaultAuthenticationSuccessHandler的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只想认证成功后,更改默认的认证过程。我做了一个被认证成功后重定向之前被调用的服务。

 命名空间PKR \\ BlogUserBundle \\处理程序;
使用Doctrine \\ ORM \\ EntityManager的;
使用PKR \\ BlogUserBundle \\服务\\ EN codeR \\ WpTransitionalEn codeR;
使用的Symfony \\分量\\ HttpFoundation \\请求;
使用的Symfony \\分量\\ HttpKernel \\登录\\ LoggerInterface;
使用的Symfony \\分量\\安全\\核心\\认证\\令牌\\ TokenInterface;
使用的Symfony \\分量\\安全\\ HTTP \\认证\\ AuthenticationSuccessHandlerInterface;
使用的Symfony \\分量\\安全\\ HTTP \\认证\\响应;类AuthenticationSuccessHandler实现AuthenticationSuccessHandlerInterface
{    保护$的EntityManager = NULL;
    保护$记录= NULL;
    保护$连接codeR = NULL;    公共职能__construct($的EntityManager EntityManager的,LoggerInterface $记录仪,WpTransitionalEn codeR $连接codeR)
    {
        $这个 - >的EntityManager = $的EntityManager;
        $这个 - >记录器= $记录;
        $这个 - > EN codeR = $连接codeR;
    }    / **
    *当一个交互式的验证尝试成功这就是所谓的。这个
    *由认证听众继承称为
    * AbstractAuthenticationListener。
    *
    * @参数请求$请求
    * @参数TokenInterface $令牌
    *
    * @返回响应永远不能为null
    * /
    公共职能onAuthenticationSuccess(请求$要求,TokenInterface $令牌)
    {
        $ USER = $ token->的getUser();
        $ newPass = $请求 - >获取('_密码');
        $用户可> setUserPassword($这个 - > EN codeR-> EN codePassword($ newPass,NULL));
        $这个 - > entityManager->坚持($用户);
        $这个 - > entityManager->的flush();
        //做重定向
    }
}

在services.yml

 服务:
    pkr_blog_user.wp_transitional_en codeR:
        类:%pkr_blog_user.wp_transitional_en coder.class%
        参数:
            成本:%pkr_blog_user.wp_transitional_en coder.cost%
            记录:@Logger
    pkr_blog_user.login_success_handler:
        等级:PKR \\ BlogUserBundle \\处理器\\ AuthenticationSuccessHandler
        参数:
            entity_manager:@ doctrine.orm.entity_manager
            记录:@Logger
            EN codeR:@ pkr_blog_user.wp_transitional_en codeR

和在security.yml

 防火墙:
    开发:
        模式:^ /(_(分析器| WDT)| CSS |图片| JS)/
        安全性:假的    secured_area:
        模式:^ /
        匿名:〜
        form_login:
            login_path:pkr_blog_admin_login
            check_path:pkr_blog_admin_login_check
            success_handler:pkr_blog_user.login_success_handler
        登出:
            路径:pkr_blog_admin_logout
            目标:/

我想要实现的是仅仅改变默认的行为一点,所以我想,为什么不延长 DefaultAuthenticationSuccessHandler ,添加一些 onSuccessHandler( )和呼叫父:: onSucessHandler()。我想,问题是,我不知道如何安全参数(在security.yml集)添加到我的扩展类构造函数。 DefaultAuthenticationSuccessHandler使用HttpUtils和$ options数组:

  / **
 *构造函数。
 *
 * @参数HttpUtils $ httpUtils
 *处理一个成功的认证尝试@参数数组$选择选项。
 * /
公共职能__construct(HttpUtils $ httpUtils,数组$选项)
{
    $这个 - > httpUtils = $ httpUtils;    $这个 - >选项= array_merge(阵列(
        always_use_default_target_path'=>假,
        default_target_path'=> '/',
        login_path'=> '/登录',
        target_path_parameter'=> _target_path',
        use_referer'=>假,
    ),$选项);
}

所以我的扩展类的构造函数应该是这样的:

  //类扩展DefaultAuthenticationSuccessHandler
    保护$的EntityManager = NULL;
    保护$记录= NULL;
    保护$连接codeR = NULL;    公共职能__construct(HttpUtils $ httpUtils,数组$选项,$的EntityManager EntityManager的,LoggerInterface $记录仪,WpTransitionalEn codeR $连接codeR)
    {
        $这个 - >的EntityManager = $的EntityManager;
        $这个 - >记录器= $记录;
        $这个 - > EN codeR = $连接codeR;
    }

这是很容易HttpUtils服务添加到我的 services.yml ,但是与选项参数?

 服务:
    pkr_blog_user.wp_transitional_en codeR:
        类:%pkr_blog_user.wp_transitional_en coder.class%
        参数:
            成本:%pkr_blog_user.wp_transitional_en coder.cost%
            记录:@Logger
    pkr_blog_user.login_success_handler:
        等级:PKR \\ BlogUserBundle \\处理器\\ AuthenticationSuccessHandler
        参数:
            httputils:@ security.http_utils
            选项​​:[] #WHAT在这里加入?
            entity_manager:@ doctrine.orm.entity_manager
            记录:@Logger
            EN codeR:@ pkr_blog_user.wp_transitional_en codeR


解决方案

如果你只有一个成功/你的应用程序定义的故障处理程序,有一个稍微容易的方式来做到这一点。而不是定义为 success_handler failure_handler ,您可以覆盖 security.authentication新服务.success_handler security.authentication.failure_handler 代替。

例如:

services.yml

 服务:
    security.authentication.success_handler:
        等级:StatSidekick \\ UserBundle \\处理器\\ AuthenticationSuccessHandler
        参数:[@ security.http_utils,{}]
        标签:
             - {名称:'monolog.logger',声道:安全}    security.authentication.failure_handler:
        等级:StatSidekick \\ UserBundle \\处理器\\ AuthenticationFailureHandler
        参数:[@http_kernel,@ security.http_utils{}@Logger]
        标签:
             - {名称:'monolog.logger',声道:安全}

AuthenticationSuccessHandler.php

 < PHP
命名空间StatSidekick \\ UserBundle \\处理程序;使用的Symfony \\分量\\ HttpFoundation \\ JsonResponse;
使用的Symfony \\分量\\ HttpFoundation \\响应;
使用的Symfony \\分量\\ HttpFoundation \\请求;
使用的Symfony \\分量\\安全\\核心\\认证\\令牌\\ TokenInterface;
使用的Symfony \\分量\\安全\\ HTTP \\认证\\ DefaultAuthenticationSuccessHandler;
使用的Symfony \\分量\\安全\\ HTTP \\ HttpUtils;类AuthenticationSuccessHandler扩展DefaultAuthenticationSuccessHandler {    公共职能__construct(HttpUtils $ httpUtils,数组$选项){
        父:: __构造($ httpUtils,$选项);
    }    公共职能onAuthenticationSuccess(请求$要求,TokenInterface $令牌){
        如果($请求 - > isXmlHtt prequest()){
            $响应=新JsonResponse(阵列('成功'=>真,用户名= GT; $ token-> getUsername()));
        }其他{
            $响应=父:: onAuthenticationSuccess($要求,$令牌);
        }
        返回$反应;
    }
}

AuthenticationFailureHandler.php

 < PHP
命名空间StatSidekick \\ UserBundle \\处理程序;使用PSR \\登录\\ LoggerInterface;
使用的Symfony \\分量\\ HttpFoundation \\ JsonResponse;
使用的Symfony \\分量\\ HttpFoundation \\响应;
使用的Symfony \\分量\\ HttpFoundation \\请求;
使用的Symfony \\分量\\ HttpKernel \\ HttpKernelInterface;
使用的Symfony \\分量\\安全\\核心\\异常\\的AuthenticationException;
使用的Symfony \\分量\\安全\\ HTTP \\认证\\ DefaultAuthenticationFailureHandler;
使用的Symfony \\分量\\安全\\ HTTP \\ HttpUtils;类AuthenticationFailureHandler扩展DefaultAuthenticationFailureHandler {    公共职能__construct(HttpKernelInterface $ httpKernel,HttpUtils $ httpUtils,数组$选项,LoggerInterface $记录= NULL){
        父:: __构造($ httpKernel,$ httpUtils,$选项,$记录);
    }    公共职能onAuthenticationFailure(请求$请求的AuthenticationException $除外){
        如果($请求 - > isXmlHtt prequest()){
            $响应=新JsonResponse(阵列('成功'=>假的,'消息'= GT; $&与异常GT;的getMessage()));
        }其他{
            $响应=父:: onAuthenticationFailure($要求,$除外);
        }
        返回$反应;
    }
}

在我而言,我只是想设置的东西了,这样我可以得到一个JSON响应,当我尝试使用AJAX来验证,但原理是一样的。

这种方法的好处是,无需任何附加的工作,所有这一切都正常传递到默认处理程序中的选项应该得到正确喷射。出现这种情况是因为SecurityBundle \\ DependencyInjection \\安全\\厂是如何在框架设置:

 保护功能createAuthenticationSuccessHandler($容器的$ id,$配置)
{
    ...
    $ successHandler = $盛器> setDefinition($ successHandlerId,新DefinitionDecorator('security.authentication.success_handler'));
    $ successHandler-> replaceArgument(1,array_intersect_key($的配置,这 - $> defaultSuccessHandlerOptions));
    ...
}保护功能createAuthenticationFailureHandler($容器的$ id,$配置)
{
    ...
    $ failureHandler = $盛器> setDefinition($ ID,新DefinitionDecorator('security.authentication.failure_handler'));
    $ failureHandler-> replaceArgument(2 array_intersect_key($的配置,这 - $> defaultFailureHandlerOptions));
    ...
}

据专门查找 security.authentication.success_handler security.authentication.failure_handler 为了从合并选项你的配置到阵列中过去了。我敢肯定有一种方法来为自己服务,类似的设置的东西,但我还没看着呢。

希望有所帮助。

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 Pkr\BlogUserBundle\Handler;
use Doctrine\ORM\EntityManager;
use Pkr\BlogUserBundle\Service\Encoder\WpTransitionalEncoder;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Authentication\Response;

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
    }
}

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: Pkr\BlogUserBundle\Handler\AuthenticationSuccessHandler
        arguments:
            entity_manager: @doctrine.orm.entity_manager
            logger: @logger
            encoder: @pkr_blog_user.wp_transitional_encoder

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: /

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

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: Pkr\BlogUserBundle\Handler\AuthenticationSuccessHandler
        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

解决方案

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.

Example:

services.yml

services:
    security.authentication.success_handler:
        class:  StatSidekick\UserBundle\Handler\AuthenticationSuccessHandler
        arguments:  ["@security.http_utils", {}]
        tags:
            - { name: 'monolog.logger', channel: 'security' }

    security.authentication.failure_handler:
        class:  StatSidekick\UserBundle\Handler\AuthenticationFailureHandler
        arguments:  ["@http_kernel", "@security.http_utils", {}, "@logger"]
        tags:
            - { name: 'monolog.logger', channel: 'security' }

AuthenticationSuccessHandler.php

<?php
namespace StatSidekick\UserBundle\Handler;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
use Symfony\Component\Security\Http\HttpUtils;

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

<?php
namespace StatSidekick\UserBundle\Handler;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use Symfony\Component\Security\Http\HttpUtils;

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

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.

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 SecurityBundle\DependencyInjection\Security\Factory 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));
    ...
}

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.

Hope that helps.

这篇关于Symfony2的延长DefaultAuthenticationSuccessHandler的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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