Routes 是否可以使用Symfony`?“切换”用户`;注销“;在模仿之间?
我正在使用的网站在导航栏中为超级用户提供了一个搜索框,这样他们就可以从一组普通用户中进行选择,然后将所选用户名传递给Symfony的Routes 是否可以使用Symfony`?“切换”用户`;注销“;在模仿之间?,routes,twig,impersonation,symfony,Routes,Twig,Impersonation,Symfony,我正在使用的网站在导航栏中为超级用户提供了一个搜索框,这样他们就可以从一组普通用户中进行选择,然后将所选用户名传递给Symfony的?\u switch\u user=功能进行模拟 我正在使用jQuery返回当前页面的路由,并为所需用户添加适当的?\u switch\u user=username,如下所示: 小枝: {% if is_granted('ROLE_PREVIOUS_ADMIN') %} <form class="navbar-form navbar-left"
?\u switch\u user=
功能进行模拟
我正在使用jQuery返回当前页面的路由,并为所需用户添加适当的?\u switch\u user=username
,如下所示:
小枝:
{% if is_granted('ROLE_PREVIOUS_ADMIN') %}
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" id="search-names" class="form-control" placeholder="User name">
</div>
</form>
<li><a href="{{ path( app.request.get('_route'), {'_switch_user':'_exit'}) }}">~Return To Admin~<span class="sr-only">Return To Admin</span></a></li>
{% endif %}
$(function() {
$("#search-names").autocomplete({
source: "{{ path('usersearch') }}",
minLength: 2,
select: function (event, matched) {
console.log(matched)
window.location = window.location + '?_switch_user=' + matched.item.value
}
});
})
在上面,我必须包含~Return to Admin~
链接,以便超级用户可以“注销”每个模拟-否则Symfony返回一个错误,表示另一个交换机用户已经登录
如果他们可以从一个普通用户切换到另一个用户,而不必每次都请求?\u switch\u user=\u exit
(尽管我仍然会保留按钮,因为当他们只执行管理员任务时需要它)
有没有一个简单的方法来实现这一点?我发现一篇文章建议通过创建一个新的listener“”来解决这个问题(他们文章中的“第二个功能”),但是我无法实现这一点,我想知道这是否是由于Symfony 3的结构差异造成的?我终于有空继续修改您链接到Symfony 3的代码。下面的代码应使“返回管理员”功能如链接中所述,并使其能够在已切换时直接切换到其他用户
<?php
namespace AppBundle\Listener;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\Security\Http\Firewall\SwitchUserListener;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class MySwitchUserListener extends SwitchUserListener
{
private $useOverrideUri = true;
public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();
if( !$request->get( $this->usernameParameter ) )
return;
if('_exit' === $request->get( $this->usernameParameter ) )
$this->tokenStorage->setToken( $this->attemptExitUser( $request ) );
else{
try{
$this->tokenStorage->setToken( $this->attemptSwitchUser( $request ) );
}catch( AuthenticationException $e ){
throw new \LogicException(sprintf('Switch User failed: "%s"', $e->getMessage()));
}
}
$request->query->remove( $this->usernameParameter );
$overrideUri = $session->get( 'onSwitchURI', NULL );
if( $request->get( 'returnTo' ) ){
$session->set( 'onSwitchURI', $request->get( 'returnTo' ) );
$request->query->remove( 'returnTo' );
}
else
$session->remove( 'onSwitchURI' );
$request->server->set( 'QUERY_STRING', http_build_query( $request->query->all() ) );
$response = new RedirectResponse( $request->getUri(), 302 );
$event->setResponse( $response );
}
private function attemptSwitchUser(Request $request)
{
$token = $this->tokenStorage->getToken();
$originalToken = $this->getOriginalToken($token);
if (false !== $originalToken) {
if ($token->getUsername() === $request->get($this->usernameParameter)) {
return $token;
}
$token = $originalToken;
$this->useOverrideUri = false;
}
if (false === $this->accessDecisionManager->decide($token, array($this->role)))
throw new AccessDeniedException();
$username = $request->get($this->usernameParameter);
if(null !== $this->logger)
$this->logger->info('Attempting to switch to user.', array('username' => $username));
$user = $this->provider->loadUserByUsername($username);
$this->userChecker->checkPostAuth($user);
$roles = $user->getRoles();
$roles[] = new SwitchUserRole( 'ROLE_PREVIOUS_ADMIN', $token );
$token = new UsernamePasswordToken( $user, $user->getPassword(), $this->providerKey, $roles );
if (null !== $this->dispatcher) {
$switchEvent = new SwitchUserEvent($request, $token->getUser());
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
}
return $token;
}
}
我在您提供的链接和Symfony 3代码中看到的最大区别是,该链接使用了已被弃用的SecurityContext。看看新的SwitchUserListener的链接,你应该能够很容易地将链接的技术应用到新的签名中。非常感谢你花时间来解决这个问题-我还没有能够实现它,但一旦我回到那个项目,我会做的!总是乐于助人。我参与的一个项目很可能最终需要这个功能(功能爬行已经变得非常糟糕了,哈哈),所以它对我们双方都有帮助。我可能只是在这里看着我自己试图解决这些问题。