我正在编写Guards来处理我的Symfony 3应用程序的OAuth。
作为其中的一部分,在我的一项服务中,我需要生成一个绝对URL以作为回调URL发送到Twitter。
#services.yml
...
app.twitter_client:
class: MyApiBundle\Services\TwitterClient
arguments:
- %twitter_client_id%
- %twitter_client_secret%
- connect_twitter_check
- '@request_stack'
- '@router'
- '@logger'
app.twitter_authenticator:
class: MyApiBundle\Security\TwitterAuthenticator
arguments:
- '@app.twitter_client'
- '@logger'
记录器是临时调试。
#TwitterClient.php service
...
use Monolog\Logger;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;
class TwitterClient
{
/**
* TwitterClient constructor.
* @param string $identifier
* @param string $secret
* @param string $callbackUrl
* @param RequestStack $requestStack
* @param RouterInterface $router
* @param Logger $logger
*/
public function __construct(
string $identifier,
string $secret,
string $callbackUrl,
RequestStack $requestStack,
RouterInterface $router,
Logger $logger
) {
$callbackUrl = $router->generate($callbackUrl, [], RouterInterface::ABSOLUTE_URL);
$logger->info($callbackUrl);
...
}
当它将$callbackUrl
输出到日志时,它只是说localhost,即使我使用不同的URL访问它。
http://localhost/connect/twitter/check
但如果我从我的控制器中做同样的事情,它会输出完整的正确URL。
#TwitterController.php
...
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
class TwitterController extends Controller
{
/**
* @Route("/connect/twitter")
* @return RedirectResponse
*/
public function connectAction()
{
/** @var RouterInterface $router */
$router = $this->container->get('router');
$callbackUrl = $router->generate('connect_twitter_check', [], RouterInterface::ABSOLUTE_URL);
/** @var Logger $logger */
$logger = $this->container->get('logger');
$this->container->get('logger')
->info($callbackUrl);
...
输出:
https://dev.myapi.com:8082/app_dev.php/connect/twitter/check
我的主机文件中设置了dev.myapi.com
域,并指向localhost,以便更轻松地区分本地应用,并使其更易于与OAuth服务集成。
答案 0 :(得分:0)
我设法通过设置路由器上下文来解决这个问题。 我已经加载了RequestStack以访问用户的IP,因此我用它来设置Route的上下文,然后路由器按预期工作。 我遇到problems试图在构造函数中使用RequestStack,所以我最终重构它,以便尽可能晚地使用RequestStack。
class TwitterClient
{
private $identifier;
private $secret;
private $callbackUrl;
private $requestStack;
private $router;
private $server;
/**
* TwitterClient constructor.
*
* @param string $identifier
* @param string $secret
* @param string $callbackUrl
* @param RequestStack $requestStack
* @param RouterInterface $router
*/
public function __construct(
string $identifier,
string $secret,
string $callbackUrl,
RequestStack $requestStack,
RouterInterface $router
) {
$this->identifier = $identifier;
$this->secret = $secret;
$this->callbackUrl = $callbackUrl;
$this->requestStack = $requestStack;
$this->router = $router;
}
/**
* Wait until the last moment to create the Twitter object to make sure that the requestStack is loaded.
*
* @return \League\OAuth1\Client\Server\Twitter
*/
private function getServer()
{
if (!$this->server) {
$context = new RequestContext();
$context->fromRequest($this->requestStack->getCurrentRequest());
$this->router->setContext($context);
$callbackUrl = $this->router->generate($this->callbackUrl, [], RouterInterface::ABSOLUTE_URL);
$this->server = new Twitter(
[
'identifier' => $this->identifier,
'secret' => $this->secret,
'callback_uri' => $callbackUrl,
]
);
}
return $this->server;
}
...
}