dsentker/url-signature-bundle
Symfony 4+ bundle for dsentker/url-signature. Generate signed (optionally expiring) URLs in Twig or controllers, validate signatures via DI/helper trait or annotations, and protect query/route parameters from tampering.
Install the package:
composer require dsentker/url-signature-bundle
For Symfony Flex, no additional steps are required. For manual setup, add to config/bundles.php:
Shift\UrlSignatureBundle\ShiftUrlSignatureBundle::class => ['all' => true],
Generate a signed URL in Twig:
<a href="{{ signed_url('route_name', { param: value }) }}">Secure Link</a>
This appends a cryptographic hash to the URL query string.
Verify the signature in a controller:
use Shift\UrlSignatureBundle\Utils\RequestValidator;
public function secureAction(RequestValidator $validator) {
if (!$validator->isValid()) {
throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
}
// Proceed if valid
}
$builder->signUrlFromPath('api.payment', ['amount' => 100], '+1 hour');
RequestValidator trait or annotation.path() with signed_url() in templates:
{{ signed_url('download_file', { id: file.id }, '+5 minutes') }}
'+10 minutes').?id=123&_hash=abc123).Signing URLs:
$builder->signUrl('https://example.com/pay', '+1 hour'); // Absolute URL
$builder->signUrlFromPath('route.name', ['param' => 'value']); // Route-based
Validation:
public function action(RequestValidator $validator) {
$validator->verify(); // Throws exception if invalid
}
/**
* @RequiresSignatureVerification()
*/
public function action() { ... }
Note: Useful for protecting entire routes without manual checks.Trait-Based (Legacy Controllers):
use Shift\UrlSignatureBundle\Controller\UrlSignatureTrait;
class OldController {
use UrlSignatureTrait;
public function action() {
$this->getValidator()->verify();
}
}
'+10 minutes'), absolute (\DateTime), or timestamp (1634567890) expiry.{{ signed_url('route', { id: 1 }, new \DateTime('+1 day')) }}
config/services.yaml:
parameters:
shift_url_signature.hash_algo: 'sha256' # Default: APP_SECRET
shift_url_signature.query_signature_name: '_sig' # Custom hash key
UrlSignature\HashConfiguration for bitmask flags (e.g., exclude PATH from hashing).symfony/http-foundation or symfony/routing in Laravel:
composer require symfony/http-foundation symfony/routing
config/app.php:
'providers' => [
Shift\UrlSignatureBundle\ShiftUrlSignatureBundle::class,
],
SignedPathExtension.Trait Constructor Conflicts:
UrlSignatureTrait if your controller has a constructor (PHP trait constructor limitations).UrlSignatureBuilder/RequestValidator) instead.Expiry Precision:
'+1 hour') use PHP’s date() parsing. Test edge cases like '+1 day 2 hours'.\DateTime for complex expiry logic.Hash Collisions:
MD5 is fast but collision-prone. Upgrade to sha256 in services.yaml:
shift_url_signature.hash_algo: 'sha256'
Query Parameter Ordering:
{ id: 1, sort: 'asc' } # Hash will differ from { sort: 'asc', id: 1 }
Annotation Performance:
@RequiresSignatureVerification runs before the controller action. Avoid heavy logic in annotated routes.Secret Management:
APP_SECRET. For production:
.env):
SHIFT_URL_SIGNATURE_SECRET=your_secure_key_here
services.yaml:
parameters:
shift_url_signature.secret: '%env(SHIFT_URL_SIGNATURE_SECRET)%'
Log Invalid Requests:
try {
$validator->verify();
} catch (\Exception $e) {
\Log::error('Invalid signature', ['url' => $request->getUri()]);
throw $e;
}
Manual Hash Verification:
use UrlSignature\HashConfiguration;
$config = new HashConfiguration('APP_SECRET');
$config->setAlgorithm('sha256');
$hash = $config->generateHash('https://example.com?param=value');
Disable Validation Temporarily:
$validator->setEnabled(false); // If supported in your version
Custom Hash Algorithms:
UrlSignature\HashConfiguration to support algorithms like argon2 or blake3.Additional Query Parameters:
# services.yaml
shift_url_signature.configuration.default:
calls:
- method: setHashMask
arguments: [0b00001] # Only hash the scheme (adjust bitmask)
Laravel-Specific Extensions:
UrlSignatureBuilder:
facade(UrlSignatureBuilder::class, 'UrlSignature');
php artisan vendor:publish --provider="Shift\UrlSignatureBundle\ShiftUrlSignatureBundle"
_hash query parameters are not logged in server logs or browser dev tools.csrf_token for forms to defend against both URL tampering and CSRF.How can I help you explore Laravel packages today?