Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[WIP] Kernel refactor #6459

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 11, 2013
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[HttpKernel] added a URL signer mechanism for hincludes
  • Loading branch information
fabpot committed Jan 10, 2013
commit 892f00ffeeb1e392e0fb0373dfd94b8abd3f194e
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@
<service id="http_content_renderer.strategy.hinclude" class="%http_content_renderer.strategy.hinclude.class%">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strategies could be marked as private, allowing to inline them in the container

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that, but because of a bug in the PHPDumper, that's not possible for hinclude. I'm working on fixing the bug so that we can use private services later on.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see #6565 for the bug fix

<tag name="kernel.content_renderer_strategy" />
<argument type="service" id="templating" />
<argument type="service" id="uri_signer" />
<argument>%http_content_renderer.strategy.hinclude.global_template%</argument>
<call method="setUrlGenerator"><argument type="service" id="router" /></call>
</service>

<!-- FIXME: make the listener registration optional via a configuration setting? -->
<service id="http_content_renderer.listener.router_proxy" class="%http_content_renderer.listener.router_proxy.class%">
<tag name="kernel.event_subscriber" />
<argument type="service" id="uri_signer" />
</service>

</services>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<parameter key="cache_warmer.class">Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate</parameter>
<parameter key="cache_clearer.class">Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer</parameter>
<parameter key="file_locator.class">Symfony\Component\HttpKernel\Config\FileLocator</parameter>
<parameter key="uri_signer.class">Symfony\Component\HttpKernel\UriSigner</parameter>
</parameters>

<services>
Expand Down Expand Up @@ -51,5 +52,9 @@
<argument type="service" id="kernel" />
<argument>%kernel.root_dir%/Resources</argument>
</service>

<service id="uri_signer" class="%uri_signer.class%">
<argument>%kernel.secret%</argument>
</service>
</services>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\UriSigner;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
Expand All @@ -28,6 +29,13 @@
*/
class RouterProxyListener implements EventSubscriberInterface
{
private $signer;

public function __construct(UriSigner $signer)
{
$this->signer = $signer;
}

/**
* Fixes request attributes when the route is '_proxy'.
*
Expand All @@ -43,16 +51,22 @@ public function onKernelRequest(GetResponseEvent $event)
return;
}

$this->checkRequest($request);
$this->validateRequest($request);

parse_str($request->query->get('path', ''), $attributes);
$request->attributes->add($attributes);
$request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params'), $attributes));
$request->query->remove('path');
}

protected function checkRequest(Request $request)
protected function validateRequest(Request $request)
{
// is the Request safe?
if (!$request->isMethodSafe()) {
throw new AccessDeniedHttpException();
}

// does the Request come from a trusted IP?
$trustedIps = array_merge($this->getLocalIpAddresses(), $request->getTrustedProxies());
$remoteAddress = $request->server->get('REMOTE_ADDR');
foreach ($trustedIps as $ip) {
Expand All @@ -61,6 +75,11 @@ protected function checkRequest(Request $request)
}
}

// is the Request signed?
if ($this->signer->check($request->getUri())) {
return;
}

throw new AccessDeniedHttpException();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,40 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Templating\EngineInterface;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\UriSigner;

/**
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HIncludeRenderingStrategy implements RenderingStrategyInterface
class HIncludeRenderingStrategy extends GeneratorAwareRenderingStrategy
{
private $templating;
private $globalDefaultTemplate;
private $signer;

public function __construct($templating, $globalDefaultTemplate = null)
public function __construct($templating, UriSigner $signer = null, $globalDefaultTemplate = null)
{
if (!$templating instanceof EngineInterface && !$templating instanceof \Twig_Environment) {
throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of \Twig_Environment or Symfony\Component\Templating\EngineInterface');
}

$this->templating = $templating;
$this->globalDefaultTemplate = $globalDefaultTemplate;
$this->signer = $signer;
}

public function render($uri, Request $request = null, array $options = array())
{
if ($uri instanceof ControllerReference) {
// FIXME: can we sign the proxy URL instead?
throw new \LogicException('You must use a proper URI when using the Hinclude rendering strategy.');
if (null === $this->signer) {
throw new \LogicException('You must use a proper URI when using the Hinclude rendering strategy or set a URL signer.');
}

$uri = $this->signer->sign($this->generateProxyUri($uri, $request));
}

$defaultTemplate = $options['default'] ?: null;
$defaultTemplate = isset($options['default']) ? $options['default'] : null;
$defaultContent = null;

if (null !== $defaultTemplate) {
Expand Down
72 changes: 72 additions & 0 deletions 72 src/Symfony/Component/HttpKernel/UriSigner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\HttpKernel;

/**
* UriSigner.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class UriSigner
{
private $secret;

/**
* Constructor.
*
* @param string $secret A secret
*/
public function __construct($secret)
{
$this->secret = $secret;
}

/**
* Signs a URI.
*
* The given URI is signed by adding a _hash query string parameter
* which value depends on the URI and the secret.
*
* @param string $uri A URI to sign
*
* @return string The signed URI
*/
public function sign($uri)
{
return $uri.(false === (strpos($uri, '?')) ? '?' : '&').'_hash='.$this->computeHash($uri);
}

/**
* Checks that a URI contains the correct hash.
*
* @param string $uri A signed URI
*
* @return Boolean True if the URI is signed correctly, false otherwise
*/
public function check($uri)
{
if (!preg_match('/(\?|&)_hash=(.+?)(&|$)/', $uri, $matches, PREG_OFFSET_CAPTURE)) {
return false;
}

// the naked URI is the URI without the _hash parameter (we need to keep the ? if there is some other parameters after)
$offset = ('?' == $matches[1][0] && '&' != $matches[3][0]) ? 0 : 1;
$nakedUri = substr($uri, 0, $matches[0][1] + $offset).substr($uri, $matches[0][1] + strlen($matches[0][0]));

return $this->computeHash($nakedUri) === $matches[2][0];
}

private function computeHash($uri)
{
return urlencode(base64_encode(hash_hmac('sha1', $uri, $this->secret, true)));
}
}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.