dsentker / url-signature-bundle
一个用于创建URL签名的symfony 4 bundle
Requires
- php: ^7.2 || ^8.0 || ^8.1 || ^8.2
- doctrine/annotations: ^1.5.0|^2.0
- dsentker/url-signature: ^1.2.0
- symfony/http-foundation: ~4.0|^5.0|^6.0
- symfony/http-kernel: ~4.0|^5.0|^6.0
- symfony/twig-bridge: ~4.0|^5.0|^6.0
Requires (Dev)
- phpstan/phpstan: ^0.12.3
- phpunit/phpunit: ^7.0
- sensio/framework-extra-bundle: ^5.2
- symfony/browser-kit: ^4.0|^5.0|^6.0
- symfony/css-selector: ^4.2|^5.0|^6.0
- symfony/dom-crawler: ^4.0|^5.0|^6.0
- symfony/expression-language: ^4.0|^5.0|^6.0
- symfony/finder: ^4.0|^5.0|^6.0
- symfony/framework-bundle: ^4.1.2|^5.0|^6.0
- symfony/phpunit-bridge: ^4.1.8|^5.0|^6.0
- symfony/security-bundle: ^4.0|^5.0|^6.0
- symfony/twig-bundle: ^4.0|^5.0|^6.0
- symfony/yaml: ^4.0|^5.0|^6.0
- twig/twig: ~1.12|~2.0
README
这是一个为 url-signature 库而设计的 Symfony >=4 bundle。
此 bundle 允许您通过在查询字符串中添加签名来构建URL,以防止用户修改URL部分。有关更详细的说明,请查看 url-signature 库的 README。
功能
- 在 Twig 模板中生成 URL
- 使用控制器助手特质生成和验证 URL
- 在控制器中使用依赖注入生成和验证 URL
- 在控制器中使用注解进行 URL 验证
安装
使用 composer 安装此 bundle
require dsentker/url-signature-bundle
如果您使用 Symfony Flex,则无需再进行任何操作。否则,您必须像这样将 bundle 包含在您的 <root>/config/bundles.php
中
<?php return [ // ... Shift\UrlSignatureBundle\ShiftUrlSignatureBundle::class => ['all' => true], ];
用法
在您的 Twig 模板中创建已签名的 URL
此 bundle 包含一个 twig 扩展,可以从任何路由名称创建 URL: signed_url()
(以及其别名 signed_path()
)与您可能已经使用过多次的 symfony / twig 函数 path()
类似。signed_path
期望一个路由名称作为第一个参数,以及可选的作为数组的查询数据
<!-- Generating a link --> <a href="{{ path('member_detail', { id: user.id }) }}">A Link </a> <!-- A link with a hash signature --> <a href="{{ signed_url('member_detail', { id: user.id }) }}">A Link with a signature</a>
这两个链接都指向同一个目标,但通过 signed_url(...)
创建的链接在查询字符串中有一个哈希值。此哈希值可以在目标控制器中进行验证。
要为 URL 设置过期日期,请传递日期作为第三个参数
<a href="{{ signed_url('member_detail', { id: user.id }, '+10 minutes') }}">A Link with a signature, expires in 10 minutes</a>
过期值可以是
- 一个相对字符串(可由 date() 函数解析)
- 一个 \DateTime 对象
- 一个整型时间戳
如果哈希值在过期时间之后进行检查,则它无效。
在控制器中签名 URL
使用依赖注入获取 Shift\UrlSignatureBundle\Utils\UrlSignatureBuilder
实例
use Shift\UrlSignatureBundle\Utils\UrlSignatureBuilder; class ExampleController extends AbstractController { /** * @Route("/member/detail/{id}", name="member_detail") */ public function index(User $user, UrlSignatureBuilder $builder) { // Just like the Twig function, the UrlSignatureBuilder offers in the third // parameter to set an expiration date. $hashedUrl = $builder->signUrlFromPath('example_path', ['param1' => 'value1'], '+10 minutes'); // You can also create a signature for a regular URL (without referring to a route path) $hashedUrl = $builder->signUrl('https://example.com/foo', '+10 minutes'); }
验证 URL
此 bundle 在控制器中提供了几种验证 URL 签名的方法。
使用依赖注入验证签名(推荐)
将 Shift\UrlSignatureBundle\Utils\RequestValidator
实例注入到您的操作中
use Shift\UrlSignatureBundle\Utils\RequestValidator; class ExampleController extends AbstractController { /** * @Route("/member/detail/{id}", name="member_detail") */ public function index(User $user, RequestValidator $signatureValidator) { if(!$signatureValidator->isValid()) { // is Signature missing or invalid? Show an alert, redirect or do something you like } // Alternatively, you can use this method. It throws an exception if the hash value // is missing or not valid. $signatureValidator->verify(); // There is no need to also inject the request object to your // action method as it is provided by RequestValidator instance. $request = $signatureValidator->getRequest(); }
使用注解验证签名
像以下示例一样注解您的控制器操作
use Shift\UrlSignatureBundle\Annotation\RequiresSignatureVerification; class ExampleController extends AbstractController { /** * @RequiresSignatureVerification() * * @Route("/member/detail/{id}", name="member_detail") */ public function index(User $user) { // ... } }
如果存在该注解,则事件监听器会检查传入的请求 URL。如果签名缺失(或无效),则在调用您的操作之前会抛出 \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
。请确保在抛出 AccessDeniedException 时给用户一个有用的响应(当然,这也适用于此 bundle 的使用)。
使用特质构建哈希 URL 并验证签名
此 bundle 包含一个特质,可以更轻松地访问构建器和请求验证器:
use Shift\UrlSignatureBundle\Controller\UrlSignatureTrait; class SingleActionController extends AbstractController { use UrlSignatureTrait; /** * @Route("/member/detail/{id}", name="member_detail") */ public function index(User $user) { /** @var Shift\UrlSignatureBundle\Utils\UrlSignatureBuilder $builder */ $builder = $this->getBuilder(); /** @var Shift\UrlSignatureBundle\Utils\RequestValidator $validator */ $validator = $this->getValidator(); } }
注意:特质有自己的构造函数。如果您的控制器已经有一个构造函数,则不应使用此特质。有关“特质中的构造函数”的更多信息,请参阅 StackOverflow。
高级用法
自定义配置
配置已经通过服务容器完成。要创建签名,需要一个密钥。通过配置,此密钥等同于您项目根目录下 .env 文件中的 APP_SECRET 的值。
正如您所知,您可以在您的 config/services.yaml
中覆盖参数和依赖项。以下是一个示例
parameters: shift_url_signature.hash_algo: 'MD5' shift_url_signature.query_signature_name: '_hash'
请查看此存储库中的 服务容器配置文件,以了解您需要调整的内容。
以下是哈希配置的完整示例
shift_url_signature.configuration.default: class: UrlSignature\HashConfiguration shared: true arguments: ['%shift_url_signature.secret%'] calls: - method: setAlgorithm arguments: - '%shift_url_signature.hash_algo%' - method: setHashMask arguments: - !php/const UrlSignature\HashConfiguration::FLAG_HASH_SCHEME - !php/const UrlSignature\HashConfiguration::FLAG_HASH_HOST - !php/const UrlSignature\HashConfiguration::FLAG_HASH_PORT - !php/const UrlSignature\HashConfiguration::FLAG_HASH_PATH - !php/const UrlSignature\HashConfiguration::FLAG_HASH_QUERY - method: setSignatureUrlKey arguments: ['%shift_url_signature.query_signature_name%'] - method: setTimeoutUrlKey arguments: ['%shift_url_signature.query_expires_name%']
对于 setHashMask
方法的奇怪参数不要感到惊讶 - 我没有找到在 services.yaml 中设置位掩码的更好解决方案。
提交错误和功能请求
错误和功能请求在 GitHub 上进行跟踪。
待办事项
- 创建更多测试。我期待着每一个支持。
- 根据即将到来的 Symfony >= 5.0 的新目录结构重构此包
测试
./vendor/bin/phpunit Shift/UrlSignatureBundle/Tests/
或者,如果您使用 Windows
.\vendor\bin\phpunit.bat Shift/UrlSignatureBundle/Tests/ --configuration phpunit.xml