mortimer333 / api-skeleton
API 骨架
Requires
- php: >=8.1
- ext-bcmath: *
- ext-ctype: *
- ext-iconv: *
- ext-json: *
- ext-mbstring: *
- ext-sodium: *
- beberlei/doctrineextensions: dev-master
- codeception/mockery-module: ^0.5.0
- codeception/module-rest: ^3.3
- doctrine/doctrine-bundle: ^2.6
- doctrine/doctrine-migrations-bundle: ^3.2
- doctrine/orm: ^2.12
- nelmio/api-doc-bundle: ^4.10
- symfony/asset: 6.4.*
- symfony/console: >=4.4.24 <7.0
- symfony/flex: ^2
- symfony/framework-bundle: ^4.4 || ^5.4 || ^6.0
- symfony/http-kernel: 6.4.*
- symfony/monolog-bundle: ^3.8
- symfony/process: ^6.4
- symfony/proxy-manager-bridge: 6.4.*
- symfony/rate-limiter: 6.4.*
- symfony/runtime: 6.4.*
- symfony/security-bundle: ^6.4
- symfony/twig-bundle: 6.4.*
- symfony/validator: ^6.4
- symfony/yaml: 6.4.*
- web-token/jwt-bundle: ^3.1
- web-token/jwt-checker: ^3.1
- web-token/jwt-console: ^3.1
- web-token/jwt-encryption: ^3.1
- web-token/jwt-encryption-algorithm-aesgcm: ^3.1
- web-token/jwt-encryption-algorithm-rsa: ^3.1
- web-token/jwt-nested-token: ^3.1
- web-token/jwt-signature: ^3.1
- web-token/jwt-signature-algorithm-rsa: ^3.1
Requires (Dev)
- codeception/codeception: ^5.0
- codeception/module-asserts: ^3.0
- codeception/module-datafactory: ^3.0
- codeception/module-db: ^3.1
- codeception/module-doctrine2: ^3.0
- codeception/module-phpbrowser: ^3.0
- codeception/module-symfony: ^3.1
- codeception/stub: ^4.0
- codeception/verify: ^2.2
- doctrine/doctrine-fixtures-bundle: ^3.4
- ekino/phpstan-banned-code: ^1.0
- friendsofphp/php-cs-fixer: ^3.13
- mockery/mockery: ^1.5
- phpmd/phpmd: @stable
- phpstan/extension-installer: ^1.2
- phpstan/phpstan: ^1.9
- phpstan/phpstan-doctrine: ^1.3
- squizlabs/php_codesniffer: ^3.7
- symfony/dotenv: >=4.4.24 <7.0
- symfony/maker-bundle: ^1.48
- symfony/stopwatch: 6.4.*
- vimeo/psalm: ^5.1
Conflicts
This package is auto-updated.
Last update: 2024-09-19 22:40:29 UTC
README
安全检查表
https://cheatsheetseries.owasp.ac.cn/index.html
- 检查泄露的密码 - https://haveibeenpwned.com/Passwords
Swagger
https://symfony.com.cn/bundles/NelmioApiDocBundle/current/index.html
- 只有名称以
api.
开头的路由会在 Swagger 中显示
https://zircote.github.io/swagger-php/guide/attributes.html
nelmio/NelmioApiDocBundle#1990
https://swagger.org.cn/docs/specification/about/
安全性
https://symfony.com.cn/doc/current/security.html
- #[CurrentUser] 属性不起作用,请使用
Symfony\Component\Security\Core\Security::getUser()
代替 - symfony/symfony#40333
CSRF 令牌
如果使用 API 平台,CSRF 令牌应由前端生成并添加到头中。让我们在用户登录时创建它,保存在 cookie 中并重复使用。它将在浏览器、系统、IP 中设置少量信息
- 浏览器
- 系统
- IP
这将足以确定用户突然更改并注销。我们还将添加加盐的应用程序密钥用于 CSRF。
电子邮件验证
https://github.com/symfonycasts/verify-email-bundle
秘密
我们将使用 symfony vault - https://symfony.com.cn/doc/current/configuration/secrets.html
- 在 dev 上可以从 config/secrets/dev/ 提交密钥
- 永远不要提交私钥 - config/secrets/dev/dev.decrypt.private.php 在 PROD
- 使用
APP_RUNTIME_ENV=prod php bin/console secrets:generate-keys
运行 prod - 通过
secrets:generate-keys --rotate
定期更改安全密钥的脚本
- 使用
- 要设置新环境:
php bin/console secrets:set [名称]
固定装置
要重置测试数据库并填充新数据,请使用固定装置
APP_ENV=test php bin/console doctrine:fixtures:load
或
make reset-test-env
测试
我们使用 codeception(它是基于 PHPUint 的)
- 验证 BDD 断言(您可能需要进入实体类,因为 codeception 改变了函数的名称 -
vendor/codeception/verify/src/Codeception/Verify/Verifiers/VerifyAny.php
) - https://github.com/Codeception/Verify/blob/master/docs/supported_verifiers.md - 更改设置后使用
php vendor/bin/codecept build
生成方法 - https://github.com/Codeception/symfony-module-tests
- 创建 Api 套件并将 URL 替换为您的本地 URL
actor: ApiTester modules: enabled: - REST: url: http://api.boardmeister.local/ # <-- url depends: Symfony part: Json - Symfony: app_path: 'src' environment: 'test'
- 以 www-data 运行测试以避免权限问题:
sudo runuser -u www-data make before-push
- symfony 模块
- 要创建测试,您必须运行
- 对于单元测试:
php vendor/bin/codecept generate:test Unit Dir/TestNameWithoutTestAtEnd
- 对于集成测试:
php vendor/bin/codecept generate:test Integration Dir/TestNameWithoutTestAtEnd
- 对于 API 测试:
php vendor/bin/codecept generate:test Api Dir/TestNameWithoutTestAtEnd
- 对于单元测试:
- 运行测试:
php vendor/bin/codecept run
- 运行详细测试:
php vendor/bin/codecept run --steps
或php vendor/bin/codecept run --debug
- 运行带覆盖率:
DEBUG_MODE=coverage php vendor/bin/codecept run --coverage --coverage-xml --coverage-html
- 运行仅
- 单元测试:
php vendor/bin/codecept run Unit
- 集成测试:
php vendor/bin/codecept run Integration
- API 测试:
php vendor/bin/codecept run Api
- 单次测试:
php vendor/bin/codecept run Integration SigninCest.php
或完整路径php vendor/bin/codecept run tests/acceptance/SigninCest.php
(https://codeception.com/docs/GettingStarted#running-tests)
- 单元测试:
- 实用知识
_before
在每个测试之前执行_after
在每个测试后执行(如果没有错误发生)_failed
在每个失败的测试后执行_passed
在每个通过测试后执行_inject
用于注入服务(https://codeception.com/docs/AdvancedUsage#dependency-injection)- 要跳过测试,可以使用
#[Skip]
(https://codeception.com/docs/AdvancedUsage#skip-tests) - 类似于控制器,您可以分组测试并运行分组(https://codeception.com/docs/AdvancedUsage#groups)
使用 Codeception\Attribute\Group;
#[Group('admin')]
php vendor/bin/codecept run -g admin -g editor
- 而不是提供者,您可以使用 Examples: (https://codeception.com/docs/AdvancedUsage#examples-attribute)
#[Examples('/api', 200)]
- 或者如果您需要一个函数
#[DataProvider('pageProvider')]
- 生成 JUnit XML 输出
php vendor/bin/codecept run --steps --xml --html
- 断言
- $this->assertEquals()
- $this->assertContains()
- $this->assertFalse()
- $this->assertTrue()
- $this->assertNull()
- $this->assertEmpty()
- 异常
- $this->expectException(ValidationException::class);
- $this->expectExceptionMessageMatches('#Nieprawidłowy typ marki#');
PHP Mess Detector
要抑制警告,使用 @SuppressWarnings(PHPMD.[warning name])
php vendor/bin/phpmd src text phpmd.xml php vendor/bin/phpmd tests text phpmd.xml
PHP Stan
命令
php vendor/bin/phpstan analyse src tests
要忽略单个错误,使用
- @phpstan-ignore-line
- @phpstan-ignore-next-line
要忽略一系列错误,请考虑阅读 https://phpstan.org/user-guide/ignoring-errors 并更新 ./phpstan.neon
已知错误
Could not write file: /tmp/phpstan/resultCache.php (file_put_contents(/tmp/phpstan/resultCache.php): Failed to open stream: Permission denied)
如果您以前以非当前用户身份运行分析,则缓存目录可能具有错误的所有者。将所有者更改为当前用户,然后应该一切正常
PHP Code Style Fixer
vendor/bin/php-cs-fixer fix --verbose
配置选项 - https://mlocati.github.io/php-cs-fixer-configurator/#version:3.13
PHP Code Sniffer
要忽略
- 文件:
// phpcs:ignoreFile
- 单个错误:
// phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
- 禁用和启用:
// phpcs:disable // phpcs:enable
- 单行:
// phpcs:ignore
更多信息请参阅 https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#ignoring-files-and-folders
Psalm
要抑制警告 @psalm-suppress InvalidReturnType
更多信息请参阅 https://psalm.dev/docs/running_psalm/dealing_with_code_issues/
已知问题:无法创建缓存目录
Uncaught RuntimeException: PHP Error: mkdir(): Permission denied in /var/www/html/boardmeister_internal/vendor/vimeo/psalm/src/Psalm/Config.php:2210 for command with CLI args "vendor/bin/psalm --taint-analysis" in /var/www/html/boardmeister_internal/vendor/vimeo/psalm/src/Psalm/Internal/ErrorHandler.php:75
如果您以 www-data 运行命令,请确保已创建 /var/www/.cache 目录,并且 www-data 是其所有者。
PHP
Ubuntu - update-alternatives --config php
BCMath
在 php.ini 中将 bcmath.scale 设置为 2
JWT
Header 管理器
https://web-token.spomky-labs.com/the-components/header-checker
Claim 管理器
https://web-token.spomky-labs.com/the-components/claim-checker
密钥
- https://web-token.spomky-labs.com/advanced-topics-1/security-recommendations
- 对称算法
- 256 位对称密钥和至少 2048 位 RSA 密钥
- 密钥附加
- kid:一个唯一的密钥 ID
- use:指示密钥的使用。或者是 sig(签名/验证)或者是 enc(加密/解密)。
- alg:允许与该密钥一起使用的算法。
- 密钥轮换 - 每周一次
- 令牌有效负载
- 尽可能小
- 拥有
- jti - 唯一标识符
- exp: 过期时间
- iat: 签发时间
- nbf: 时间的有效点。
- iss (签发者)
- aud (受众)
- 当使用加密令牌时,iss 和 aud 声明应复制到头部
验证
- 反序列化令牌
- 对于每个签名/接收者(在使用 Json 常规序列化模式时可能发生)
- 检查完整头部(受保护的和未受保护的)
- 验证签名(JWS)或解密令牌(JWE)
- 检查有效载荷中的声明(如果有)
如果在处理过程中发生错误,应将令牌视为无效。
必须检查头部参数。您至少应检查 alg(算法)和 enc(仅适用于 JWE)参数。crit(关键)头部参数始终被检查。
嵌套令牌
我们想要使用嵌套令牌来签名和加密令牌 - https://web-token.spomky-labs.com/advanced-topics-1/nested-tokens