dsentker/url-signature-bundle

一个用于创建URL签名的symfony 4 bundle

安装次数: 27,495

依赖者: 0

建议者: 0

安全: 0

星标: 9

关注者: 5

分支: 5

开放问题: 2

类型:symfony-bundle

1.3.0 2023-08-24 12:11 UTC

This package is auto-updated.

Last update: 2024-09-24 14:35:28 UTC


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