gpt4 book ai didi

php - Symfony2 显示 "A token was not found in the SecurityContext"而不是我的 AuthenticationException

转载 作者:可可西里 更新时间:2023-10-31 23:05:43 25 4
gpt4 key购买 nike

你好

我正尝试在 Symfony2 中为我的 api 设置某种 WSSE 身份验证。但是,在测试未经授权的调用时,我没有获取自定义的 AuthenticationException,而是从框架中获取了状态代码为 500 的 AuthenticationCredentialsNotFoundException。

对于为什么会发生这种情况有什么想法吗?这是我的代码:

WsseListener.php

<?php
namespace KrugerCorp\VOIPBundle\Security\Firewall;

use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use KrugerCorp\VOIPBundle\Security\Authentication\Token\WsseTenantToken;

class WsseListener implements ListenerInterface
{
protected $securityContext;
protected $authenticationManager;
protected $logger;

public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, LoggerInterface $logger)
{
$this->securityContext = $securityContext;
$this->authenticationManager = $authenticationManager;
$this->logger = $logger;
}

public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();

$wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/';
if (!$request->headers->has('x-wsse') || 1 !== preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches))
return;

$token = new WsseTenantToken();
$token->setUser($matches[1]);

$token->digest = $matches[2];
$token->nonce = $matches[3];
$token->created = $matches[4];

try {
$authToken = $this->authenticationManager->authenticate($token);
$this->securityContext->setToken($authToken);

return;
} catch (AuthenticationException $e) {
$failedMessage = 'WSSE login failed for '.$token->getUsername()-'. Why? '.$e->getMessage();
$this->logger->error($failedMessage);

$response = new Response();
$response->setStatusCode(403);
$response->setContent($failedMessage);
$event->setResponse($response);
return;
}

$response = new Response();
$response->setStatusCode(403);
$event->setResponse($response);
}
}

WsseProvider.php

<?php

namespace KrugerCorp\VOIPBundle\Security\Authentication\Provider;

use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\NonceExpiredException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use KrugerCorp\VOIPBundle\Security\Authentication\Token\WsseTenantToken;

class WsseProvider implements AuthenticationProviderInterface {

private $tenantProvider;
private $cacheDir;

public function __construct(UserProviderInterface $userProvider, $cacheDir)
{
$this->tenantProvider = $userProvider;
$this->cacheDir = $cacheDir;
}

public function authenticate(TokenInterface $token)
{
$tenant = $this->tenantProvider->loadUserByUsername($token->getUsername());

if (!$tenant)
throw new AuthenticationException("Bad credentials.");

if ($tenant && $this->validateDigest($token->digest, $token->nonce, $token->created, $tenant->getPassword()))
{
$authenticatedToken = new WsseTenantToken($tenant->getRoles());
$authenticatedToken->setUser($tenant);

return $authenticatedToken;
}

throw new AuthenticationException('The WSSE authentication failed.');
}

protected function validateDigest($digest, $nonce, $created, $secret)
{
if (strtotime($created) > time())
throw new AuthenticationException('The provided WSSE timestamp is in the future. Nice try.');

if (time() - strtotime($created) > 300)
throw new AuthenticationException('The timestamp is outdated.');

if (file_exists($this->cacheDir.'/'.$nonce) && file_get_contents($this->cacheDir.'/'.$nonce) + 300 > time())
throw new NonceExpiredException('Previously used nonce detected');

if (!is_dir($this->cacheDir))
mkdir($this->cacheDir, 0777, true);

file_put_contents($this->cacheDir.'/'.$nonce, time());

$expected = base64_encode(sha1(base64_decode($nonce).$created.$secret, true));

if ($digest !== $expected)
throw new AuthenticationException('Bad credentials. Digest is not as expected.');

return true;
}

public function supports(TokenInterface $token)
{
return $token instanceof WsseTenantToken;
}
}

WsseFactory.php

<?php

namespace KrugerCorp\VOIPBundle\DependencyInjection\Security\Factory;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;

class WsseFactory implements SecurityFactoryInterface
{
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
{
$providerId = 'security.authentication.provider.wsse.'.$id;
$container
->setDefinition($providerId, new DefinitionDecorator('wsse.security.authentication.provider'))
->replaceArgument(0, new Reference($userProvider));

$listenerId = 'security.authentication.listener.wsse.'.$id;
$listener = $container->setDefinition($listenerId, new DefinitionDecorator('wsse.security.authentication.listener'));

return array($providerId, $listenerId, $defaultEntryPoint);
}

public function getPosition()
{
return 'pre_auth';
}

public function getKey()
{
return 'wsse';
}

public function addConfiguration(NodeDefinition $node)
{
}
}

我的防火墙

    wsse_secured:
pattern: ^/api/.*
stateless: true
wsse: true
anonymous: false

我的服务

wsse.security.authentication.provider:
class: KrugerCorp\VOIPBundle\Security\Authentication\Provider\WsseProvider
arguments: ["", "%kernel.cache_dir%/security/nonces"]

wsse.security.authentication.listener:
class: KrugerCorp\VOIPBundle\Security\Firewall\WsseListener
arguments: ["@security.context", "@security.authentication.manager", "@logger"]
tags:
- { name: monolog.logger, channel: wsse }

和 mu bundle 类

<?php

namespace KrugerCorp\VOIPBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;
use KrugerCorp\VOIPBundle\DependencyInjection\Security\Factory\WsseFactory;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class KrugerCorpVOIPBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);

$extension = $container->getExtension('security');
$extension->addSecurityListenerFactory(new WsseFactory());
}
}

最佳答案

try {
$authToken = $this->authenticationManager->authenticate($token);
$this->securityContext->setToken($authToken);

return;
} catch (AuthenticationException $e) {
// ...
}

您只捕获了AuthenticationException!

但是

$this->authenticationManager->authenticate($token);

还会抛出不会被捕获的 NonceExpiredException

还有我的代码审查...阅读评论。

// I guess loadUserByUsername throws UsernameNotFoundException.
// Wrap it in try catch and throw new AuthenticationException("Bad credentials.");
$tenant = $this->tenantProvider->loadUserByUsername($token->getUsername());

// You will not need this...
if (!$tenant)
throw new AuthenticationException("Bad credentials.");

// $tenant always true here.
if ($tenant && $this->validateDigest($token->digest, $token->nonce, $token->created, $tenant->getPassword()))
{
$authenticatedToken = new WsseTenantToken($tenant->getRoles());
$authenticatedToken->setUser($tenant);

return $authenticatedToken;
}

关于php - Symfony2 显示 "A token was not found in the SecurityContext"而不是我的 AuthenticationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21902109/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com