Skip to content

Symfony Cheat Sheet / Symfony速查表

Introduction / 介绍

This cheat sheet aims to provide developers with security tips when building applications using the Symfony framework. It covers common vulnerabilities and best practices to ensure that your Symfony applications are secure.

本速查表旨在为使用Symfony框架构建应用程序的开发者提供安全提示。它涵盖了常见的漏洞和最佳实践,以确保您的Symfony应用程序安全。

While Symfony comes with built-in security mechanisms, developers must be aware of potential vulnerabilities and best practices to ensure the applications they build are secure. This guide aims to cover common security issues, emphasizing the importance of understanding Symfony's security features and how to utilize them effectively. Whether you're a newcomer to Symfony or an experienced developer looking to reinforce your security practices, this document serves as a valuable resource. By following the guidelines outlined here, you can strengthen the security of your Symfony applications and create a safer digital environment for users and data.

虽然Symfony自带内置的安全机制,但开发者必须意识到潜在的安全漏洞和最佳实践,以确保他们构建的应用程序安全。本指南旨在涵盖常见的安全问题,强调理解Symfony的安全功能及其有效利用的重要性。无论您是Symfony的新手还是经验丰富的开发者,希望加强安全实践,这份文档都是一份宝贵的资源。通过遵循这里概述的指南,您可以增强Symfony应用程序的安全性,为用户和数据创造一个更安全的数字环境。

Main Sections / 主要章节

Cross-Site Scripting (XSS) / 跨站脚本(XSS)

Cross-Site Scripting (XSS) is a type of attack where malicious JavaScript code is injected into a displayed variable. For example, if the value of the variable name is <script>alert('hello')</script>, and we display it in HTML like this: Hello {{name}}, the injected script will be executed when the HTML is rendered.

跨站脚本(XSS)是一种攻击类型,恶意JavaScript代码被注入到显示的变量中。例如,如果变量名称的值是 <script>alert('hello')</script>,并且我们像这样在HTML中显示它:Hello {{name}},那么注入的脚本将在HTML渲染时执行。

Symfony comes by default with twig templates that automatically protect applications from XSS attacks by using output escaping to transform variables containing special characters by wrapping the variable with {{ }} statement.

Symfony默认带有自动保护应用程序免受XSS攻击的twig模板,通过使用输出转义将包含特殊字符的变量用{{ }}语句包裹来转换变量。

<p>Hello {{name}}</p>
{# if 'name' is '<script>alert('hello!')</script>', Twig will output this:
'<p>Hello &lt;script&gt;alert(&#39;hello!&#39;)&lt;/script&gt;</p>' #}

If you are rendering a variable that is trusted and contains HTML contents, you can use Twig raw filter to disable output escaping.

如果您正在渲染一个受信任且包含HTML内容的变量,可以使用Twig原始过滤器来禁用输出转义。

<p>{{ product.title|raw }}</p>
{# if 'product.title' is 'Lorem <strong>Ipsum</strong>', Twig will output
exactly that instead of 'Lorem &lt;strong&gt;Ipsum&lt;/strong&gt;' #}

Explore the Twig output escaping documentation to gain insights into disabling output escaping for a specific block or an entire template.

探索Twig输出转义文档,以了解如何禁用特定块或整个模板的输出转义。

For other information on XSS prevention that is not specific to Symfony, you may refer to the Cross Site Scripting Prevention Cheatsheet.

有关非特定于Symfony的XSS预防信息,您可以参考跨站脚本预防速查表。

Cross-Site Request Forgery (CSRF) / 跨站请求伪造 (CSRF)

Symfony Form component automatically includes CSRF tokens in the forms, providing built-in protection against CSRF attacks. Symfony validates these tokens automatically, eliminating the need for manual intervention to safeguard your application.

Symfony表单组件自动在表单中包含CSRF令牌,提供内置的CSRF攻击防护。Symfony会自动验证这些令牌,消除手动干预以保护您的应用程序的需要。

By default the CSRF token is added as a hidden field called _token, but this can be customized with other settings on a form-by-form basis:

默认情况下,CSRF令牌作为名为_token的隐藏字段添加,但可以在表单级别根据其他设置进行自定义:

use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PostForm extends AbstractType
{

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            // ... 
            'csrf_protection' => true,  // enable/disable csrf protection for this form
            'csrf_field_name' => '_csrf_token',
            'csrf_token_id'   => 'post_item', // change arbitrary string used to generate
        ]);
    }

}

If you do not use Symfony Forms, follow Symfony's manual CSRF token generation and validation. First, install the symfony/security-csrf component:

如果您不使用Symfony表单,请遵循Symfony的手动CSRF令牌生成和验证。首先,安装symfony/security-csrf组件:

composer require symfony/security-csrf

Enable CSRF protection in config/packages/framework.yaml:

在config/packages/framework.yaml中启用CSRF保护:

framework:
    csrf_protection: true

Next, consider this HTML Twig template when a CSRF token is generated by the csrf_token() Twig function

接下来,考虑当CSRF令牌由csrf_token()Twig函数生成时的HTML Twig模板:

<form action="{{ url('delete_post', { id: post.id }) }}" method="post">
    <input type="hidden" name="token" value="{{ csrf_token('delete-post') }}">
    <button type="submit">Delete post</button>
</form>

Configure the delete_post route to accept POST, matching the form. At the start of its controller action, validate the submitted token with the same token ID (delete-post) used by Twig. Reject a missing or invalid token before performing any state change:

配置delete_post路由以接受POST请求,与表单匹配。在其控制器操作开始时,使用与Twig相同的令牌ID(delete-post)验证提交的令牌。在执行任何状态更改之前,拒绝缺失或无效的令牌:

$token = $request->request->get('token');
if (!is_string($token) || !$this->isCsrfTokenValid('delete-post', $token)) {
    throw $this->createAccessDeniedException('Invalid CSRF token.');
}

This illustrative check assumes an AbstractController action with a Request argument named $request. CSRF validation does not authorize deletion: check the caller's permission for the target post separately before deleting it.

此示例检查假设有一个名为 $request 的 Request 参数的 AbstractController 动作。CSRF 验证不授权删除:在删除之前,请单独检查调用者对目标帖子的权限。

You can find more information about CSRF not related to Symfony in Cross-Site Request Forgery (CSRF) Cheat Sheet.

有关与 Symfony 无关的 CSRF 的更多信息,请参阅 跨站请求伪造 (CSRF) 操练手册。

SQL Injection / SQL注入

SQL Injection is a type of security vulnerability that occurs when an attacker is able to manipulate a SQL query in a way that it can execute arbitrary SQL code. This can allow attackers to view, modify, or delete data in the database, potentially leading to unauthorized access or data loss.

SQL 注入是一种安全漏洞,当攻击者能够以某种方式操纵 SQL 查询,使其能够执行任意 SQL 代码时发生。这允许攻击者查看、修改或删除数据库中的数据,可能导致未经授权的访问或数据丢失。

Symfony, particularly when used with Doctrine ORM (Object-Relational Mapping), provides protection against SQL injection through prepared statements parameters. Thanks to this it is harder to mistakenly write unprotected queries, however, it is still possible. The following example shows insecure DQL usage:

Symfony,尤其是与 Doctrine ORM(对象关系映射)一起使用时,通过预处理语句参数提供对 SQL 注入的保护。因此,更难错误地编写未受保护的查询,然而,这仍然是可能的。以下示例显示了 不安全的 DQL 使用:

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class ExampleController extends AbstractController {

    public function getPost(Request $request, EntityManagerInterface $em): Response
    {
        $id = $request->query->get('id');

        $dql = "SELECT p FROM App\Entity\Post p WHERE p.id = " . $id . ";";
        $query = $em->createQuery($dql);
        $post = $query->getSingleResult();

        // ...
    }
}

The examples below show the correct ways to provide protection against SQL Injection:

以下示例显示了 正确的方法来提供对 SQL 注入的保护:

  • Using entity repository built-in method
    中文:使用实体存储库内置方法
$id = $request->query->get('id');
$post = $em->getRepository(Post::class)->findOneBy(['id' => $id]);
  • Using Doctrine DQL Language
    中文:使用 Doctrine DQL 语言
$query = $em->createQuery("SELECT p FROM App\Entity\Post p WHERE p.id = :id");
$query->setParameter('id', $id);
$post = $query->getSingleResult();
  • Using DBAL Query Builder
    中文:使用 DBAL 查询构建器
$qb = $em->createQueryBuilder();
$post = $qb->select('p')
            ->from('posts','p')
            ->where('id = :id')
            ->setParameter('id', $id)
            ->getQuery()
            ->getSingleResult();

For more information about Doctrine, you can refer to their documentation. You may also refer to the SQL Injection Prevention Cheatsheet for more information that is not specific to either Symfony or Doctrine.

关于Doctrine的更多信息,您可以参考他们的文档。您还可以参考SQL注入预防速查表,以获取不特定于Symfony或Doctrine的更多信息。

Command Injection / 命令注入

Command Injection occurs when malicious code is injected into an application system and executed. For more information refer to Command Injection Defense Cheat Sheet.

命令注入发生在恶意代码被注入到应用程序系统中并执行时。有关更多信息,请参阅命令注入防御速查表。

Consider the following example, where a file is removed using the exec() function without any input escaping:

考虑以下示例,其中使用exec()函数删除文件而没有进行任何输入转义:

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;

#[AsController]
class ExampleController 
{

    #[Route('/remove_file', methods: ['POST'])]
    public function removeFile(Request $request): Response
    {
        $filename =  $request->request->get('filename');
        exec(sprintf('rm %s', $filename));

        // ...
    }
}

In the above code, there is no validation of the user's input. Imagine what could happen if the user provides a malicious value like test.txt && rm -rf . . To mitigate this risk, it is advisable to use native PHP functions like in this case unlink() or Symfony Filesystem Component remove() method instead of exec().

在上面的代码中,没有验证用户的输入。想象一下,如果用户提供了像test.txt && rm -rf .这样的恶意值会发生什么。为了减轻这种风险,建议使用本例中的原生PHP函数unlink()或Symfony Filesystem组件的remove()方法,而不是使用exec()。

For specific PHP filesystem functions relevant to your case, you can refer to the PHP documentation or Symfony Filesystem Component documentation.

对于与您的案例相关的特定PHP文件系统函数,您可以参考PHP文档或Symfony Filesystem组件文档。

Open Redirection / 开放重定向

Open Redirection is a security flaw that occurs when a web application redirects users to a URL specified in an invalidated parameter. Attackers exploit this vulnerability to redirect users to malicious sites.

开放重定向是一种安全漏洞,当Web应用程序将用户重定向到由无效参数指定的URL时发生。攻击者利用这种漏洞将用户重定向到恶意网站。

In the provided PHP code snippet:

在提供的PHP代码片段中:

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\Routing\Annotation\Route;

class ExampleController extends AbstractController 
{

    #[Route('/dynamic_redirect', methods: ['GET'])]
    public function dynamicRedirect(#[MapQueryParameter] string $url): Response 
    {
        return $this->redirect($url);
    }
}

The controller function redirects users based on the url query parameter without proper validation. Attackers can craft malicious URLs, leading unsuspecting users to malicious sites. To prevent open redirection, always validate and sanitize user input before redirection, and avoid using untrusted input directly in redirect functions.

控制器函数根据url查询参数重定向用户,但没有进行适当的验证。攻击者可以构建恶意URL,导致用户不知不觉地访问恶意网站。为了防止开放重定向,在重定向之前始终验证和清理用户输入,并避免在重定向函数中直接使用不受信任的输入。

File Upload Vulnerabilities / 文件上传漏洞

File upload vulnerabilities are security issues that arise when an application does not properly validate and handle file uploads. It's important to ensure that file uploads are handled securely to prevent various types of attacks. Here are some general guidelines to help mitigate this issue in Symfony:

文件上传漏洞是在应用程序未能正确验证和处理文件上传时出现的安全问题。确保安全地处理文件上传对于防止各种类型的攻击至关重要。以下是一些在 Symfony 中减轻此问题的通用指南:

Validate file type and size / 验证文件类型和大小

Always validate the file type on the server side to ensure that only allowed file types are accepted. See the Symfony validation documentation. Also, consider limiting the size of uploaded files to prevent denial-of-service attacks and to ensure that your server has enough resources to handle the uploads.

始终在服务器端验证文件类型,以确保只接受允许的文件类型。请参阅 Symfony 验证文档。此外,考虑限制上传文件的大小,以防止拒绝服务攻击并确保您的服务器有足够的资源来处理上传。

Example with PHP Attributes:

使用 PHP 属性的示例:

use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints\File;

class UploadDto
{
    public function __construct(
        #[File(
            maxSize: '1024k',
            mimeTypes: [
                'application/pdf',
                'application/x-pdf',
            ],
        )]
        public readonly UploadedFile $file,
    ){}
}

Example with Symfony Form:

使用 Symfony 表单的示例:

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\File;

class FileForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('file', FileType::class, [
                'constraints' => [
                    new File([
                        'maxSize' => '1024k', 
                        'mimeTypes' => [
                            'application/pdf',
                            'application/x-pdf',
                        ],
                    ]),
                ],
            ]);
    }
}

Use unique filenames / 使用唯一的文件名

Ensure that each uploaded file has a unique name to prevent overwriting existing files. You can use a combination of a unique identifier and the original filename to generate a unique name.

确保每个上传的文件都有一个唯一的名称,以防止覆盖现有文件。您可以使用唯一标识符和原始文件名组合生成一个唯一的名称。

Store uploaded files securely / 安全存储上传文件

Store uploaded files outside the public directory to prevent direct access. If you use a public directory to store them, configure your web server to deny access to the upload directory.

将上传文件存储在公共目录之外以防止直接访问。如果您使用公共目录来存储它们,请配置您的Web服务器拒绝访问上传目录。

Refer to the File Upload Cheatsheet to learn more.

有关更多信息,请参阅文件上传速查表。

Directory Traversal / 目录遍历

A directory or path traversal attack aims to access files and directories that are stored on a server by manipulating input data that reference files with “../” dot-dot-slash sequences and its variations or by using absolute file paths. For more details refer to OWASP Path Traversal.

目录或路径遍历攻击旨在通过操纵引用包含“../” (点-点-斜杠) 序列及其变体或使用绝对文件路径的输入数据来访问存储在服务器上的文件和目录。有关更多详细信息,请参阅OWASP路径遍历。

You can protect your application from a directory traversal attack by validating whether the absolute path of the requested file location is correct or strip out the directory information from filename input.

您可以通过验证请求的文件位置的绝对路径是否正确或从文件名输入中删除目录信息来保护您的应用程序免受目录遍历攻击。

  • Resolve the base directory and requested path with realpath(), rejecting failures. Include the directory separator in the containment check so a sibling such as /storage-private cannot match /storage.
    中文:使用 realpath() 函数解析基本目录和请求路径,拒绝失败。在包含检查中包含目录分隔符,以确保如 /storage-private 这样的兄弟目录不能匹配 /storage。
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\Routing\Annotation\Route;

class ExampleController extends AbstractController 
{

    #[Route('/download', methods: ['GET'])]
    public function download(#[MapQueryParameter] string $filename): Response 
    {
        $storagePath = $this->getParameter('kernel.project_dir') . '/storage';
        $filePath = $storagePath . '/' . $filename;

        $realBase = realpath($storagePath);
        $realPath = realpath($filePath);

        if ($realBase === false || $realPath === false
            || !str_starts_with($realPath, $realBase . DIRECTORY_SEPARATOR))
        {
            throw $this->createNotFoundException();
        }

        // Use $realPath for the authorized file operation.

    }
}

This illustrative check assumes untrusted users cannot change the directories or symbolic links between validation and file access. Check the caller's permission to access the resolved file separately.

此说明性检查假设在验证和文件访问之间,不可信用户无法更改目录或符号链接。请单独检查调用者访问解析文件的权限。

  • Strip out directory information with PHP basename function
    中文:使用PHP的basename函数删除目录信息
// ...

$storagePath = $this->getParameter('kernel.project_dir') . '/storage';
$filePath = $storagePath . '/' . basename($filename);

// ...

Dependencies vulnerabilities / 依赖项漏洞

Dependency vulnerabilities can expose your application to various risks, making it crucial to adopt best practices. Keep all Symfony components and third-party libraries up-to-date.

依赖项漏洞可能会使您的应用程序面临各种风险,因此采用最佳实践至关重要。请确保所有 Symfony 组件和第三方库保持最新状态。

Composer, the dependency manager for PHP makes it easy to update PHP packages:

Composer 是 PHP 的依赖管理器,它使得更新 PHP 包变得简单:

composer update

When using multiple dependencies, some of them may contain security vulnerabilities. To address this concern, Symfony comes with Symfony Security Checker. This tool specifically examines the composer.lock file in your project to identify any known security vulnerabilities within the dependencies that have been installed and address any potential security issues in your Symfony project.

当使用多个依赖项时,其中一些可能包含安全漏洞。为了解决这一担忧,Symfony 内置了 Symfony 安全检查器。该工具专门检查您的项目中的 composer.lock 文件,以识别已安装依赖项中的任何已知安全漏洞,并解决 Symfony 项目中可能存在的潜在安全问题。

To use Security Checker run the following command using Symfony CLI:

要使用安全检查器,请使用 Symfony CLI 运行以下命令:

symfony check:security

Cross-Origin Resource Sharing (CORS) / 跨源资源共享 (CORS)

CORS is a security feature implemented in web browsers to control how web applications in one domain can request and interact with resources hosted on other domains.

CORS 是一种在浏览器中实现的安全功能,用于控制一个域中的 Web 应用程序如何请求和与另一个域上托管的资源交互。

In Symfony, you can manage CORS policies using nelmio/cors-bundle. This bundle lets you control CORS rules precisely without changing your server settings.

在 Symfony 中,您可以使用 nelmio/cors-bundle 管理CORS策略。此包允许您精确控制 CORS 规则,而无需更改服务器设置。

To install it with Composer, run:

使用Composer安装,请运行:

composer require nelmio/cors-bundle

For Symfony Flex users, the installation generates a basic configuration file in the config/packages directory automatically. Take a look at the example configuration for routes starting with /API prefix.

对于使用Symfony Flex的用户,安装会自动在config/packages目录中生成一个基本配置文件。请查看以/API前缀开始的路由示例配置。

# config/packages/nelmio_cors.yaml
nelmio_cors:
    defaults:
        origin_regex: true
        allow_origin: ['*']
        allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
        allow_headers: ['*']
        expose_headers: ['Link']
        max_age: 3600
    paths:
        '^/api': ~  # ~ means that configurations for this path is inherited from defaults

It's advisable to enhance the security of your Symfony application by adding to your responses essential security headers as:

建议通过向响应中添加以下必要的安全头部来增强您的Symfony应用程序的安全性:

  • Strict-Transport-Security
  • X-Frame-Options
  • X-Content-Type-Options
  • Content-Security-Policy
  • X-Permitted-Cross-Domain-Policies
  • Referrer-Policy
  • Clear-Site-Data
  • Cross-Origin-Embedder-Policy
  • Cross-Origin-Opener-Policy
    中文:跨源开启策略
  • Cross-Origin-Resource-Policy
    中文:跨源资源策略
  • Cache-Control
    中文:缓存控制

To find more details about individual headers refer to the OWASP secure headers project.

要了解更多关于单个头部的详细信息,请参考OWASP安全头部项目。

In Symfony, you can add those headers either manually or automatically by listening the ResponseEvent to your to every response or configuring web servers like Nginx or Apache.

在Symfony中,您可以通过手动添加或通过监听ResponseEvent来为每个响应自动添加这些头部,或者配置Web服务器如Nginx或Apache。

use Symfony\Component\HttpFoundation\Request;

$response = new Response();
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');

Configure session cookies under framework.session in config/packages/framework.yaml. For an HTTPS application, explicitly set cookie_secure: true; auto sets it to false for HTTP requests and does not guarantee secure cookies. Keep cookie_httponly: true to prevent JavaScript from reading the cookie.

在config/packages/framework.yaml中的framework.session下配置会话Cookie。对于HTTPS应用程序,明确设置cookie_secure: true(https://symfony.com/doc/current/reference/configuration/framework.html#cookie-secure);auto将其设置为false以用于HTTP请求,并且不保证Cookie的安全性。保持cookie_httponly: true(https://symfony.com/doc/current/reference/configuration/framework.html#cookie-httponly)以防止JavaScript读取Cookie。

framework:
    session:
        cookie_secure: true
        cookie_httponly: true
        cookie_samesite: lax

Use cookie_samesite: lax, or strict where the application's navigation flows permit it. SameSite restricts cross-site cookie sending; it does not isolate all origins. For example, sibling subdomains with the same scheme can be same-site. Retain CSRF protection for state-changing requests.

使用cookie_samesite: lax或strict,前提是应用程序的导航流程允许这样做。[SameSite]限制了跨站Cookie发送(https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie#samesitesamesite-value);它不会隔离所有来源。例如,具有相同方案的兄弟子域可以是[same-site](https://developer.mozilla.org/en-US/docs/Glossary/Site)。对于状态更改请求,保留CSRF保护。

cookie_lifetime is measured in seconds: 5 means five seconds, not five minutes. Cookie expiration does not enforce a server-side session timeout. Implement server-side idle and absolute expiration as described in the Session Management Cheat Sheet.


In Symfony, sessions are managed by the framework itself and rely on Symfony's session handling mechanisms rather than PHP's default session handling via the session.auto_start = 1 directive in the php.ini file. The session.auto_start = 1 directive in PHP is used to automatically start a session on each request, bypassing explicit calls to session_start(). However, when using Symfony for session management, it's recommended to disable session.auto_start to prevent conflicts and unexpected behavior.

在 Symfony 中,会话由框架本身管理,依赖于 Symfony 的会话处理机制,而不是通过 php.ini 文件中的 session.auto_start = 1 指令使用 PHP 的默认会话处理。PHP 中的 session.auto_start = 1 指令用于在每个请求上自动启动会话,绕过对 session_start() 的显式调用。然而,当使用 Symfony 进行会话管理时,建议禁用 session.auto_start 以防止冲突和意外行为。

Authentication / 身份验证

Symfony Security) (Symfony 安全) provides a robust authentication system that includes providers, firewalls, and access controls to ensure a secure and controlled access environment. Authentication settings can be configured in config/packages/security.yaml.

  • Providers
    中文:提供者**

    Symfony authentication relies on providers to fetch user information from various storage types such as databases, LDAP, or custom sources. Providers get users based on the defined property and load the corresponding user object.

Symfony 认证依赖于提供者从各种存储类型(如数据库、LDAP 或自定义来源)中获取用户信息。提供者根据定义的属性获取用户,并加载相应的用户对象。

In the example below [Entity User Provider](https://symfony.com/doc/current/security/user_providers.html#security-entity-user-provider) is presented which uses Doctrine to fetch user by unique identifier.

以下示例中展示了 实体用户提供者,它使用 Doctrine 通过唯一标识符获取用户。

```yaml
providers:
    app_user_provider:
        entity:
            class: App\Entity\User
            property: email
```
  • Firewalls
    中文:防火墙**

    Symfony uses firewalls to define security configurations for different parts of an application. Each firewall defines a specific set of rules and actions for incoming requests. They protect different sections of the application by specifying which routes or URLs are secured, the authentication mechanisms to use, and how to handle unauthorized access. A firewall can be associated with specific patterns, request methods, access controls, and authentication providers.

Symfony 使用防火墙来定义应用程序不同部分的安全配置。每个防火墙定义了针对传入请求的特定规则和操作。它们通过指定受保护的路由或 URL、要使用的身份验证机制以及如何处理未经授权的访问来保护应用程序的不同部分。防火墙可以与特定模式、请求方法、访问控制和身份验证提供者相关联。

```yaml
firewalls:
    dev: # disable security on routes used in development env
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    admin: # handle authentication in /admin pattern routes
        lazy: true
        provider: app_user_provider
        pattern: ^/admin
        custom_authenticator: App\Security\AdminAuthenticator
        logout:
            path: app_logout
            target: app_login
    main: # main firewall that include all remaining routes
        lazy: true
        provider: app_user_provider
```
  • Access Control
    中文:访问控制**

    Access control determines which users can access specific parts of an application. These rules consist of path patterns and required roles or permissions. Access control rules are configured under access_control key.

访问控制决定哪些用户可以访问应用程序的特定部分。这些规则包括路径模式和所需的角色或权限。访问控制规则在 access_control 键下配置。

```yaml
access_control:
    - { path: ^/admin, roles: ROLE_ADMIN } # only user with ROLE_ADMIN role is allowed
    - { path: ^/login, roles: PUBLIC_ACCESS } # everyone can access this route
```

Error Handling Disclosure / 错误处理披露

Symfony has a robust error-handling system. By default, Symfony applications are configured to display detailed error messages only in the development environment for security reasons. In the production environment, a generic error page is shown. Symfony's error handling system also allows customized error pages based on different HTTP status codes, providing a seamless and branded user experience. Additionally, Symfony logs detailed error information, aiding developers in identifying and resolving issues efficiently.

Symfony 拥有强大的错误处理系统。默认情况下,出于安全原因,Symfony 应用程序配置为仅在开发环境中显示详细的错误消息。在生产环境中,显示一个通用的错误页面。Symfony 的错误处理系统还允许根据不同的 HTTP 状态码自定义错误页面,提供无缝且具有品牌特色的用户体验。此外,Symfony 记录详细的错误信息,帮助开发者高效地识别和解决问题。

For more information about error handling unrelated to Symfony refer to Error Handling Cheat Sheet.

有关与 Symfony 无关的错误处理更多信息,请参阅 错误处理作弊表。

Sensitive data / 敏感数据

In Symfony, the best way to store configurations like API keys, etc., is through the use of environment variables, which are dependent on the application's location. To ensure the security of sensitive values, Symfony provides a secrets management system in which values are additionally encoded using cryptographic keys and stored as secrets.

在 Symfony 中,存储配置如 API 密钥等最佳方式是通过使用环境变量,这些变量依赖于应用程序的位置。为确保敏感值的保密性,Symfony 提供了一个 秘密管理系统,其中值还使用加密密钥进行编码,并存储为 秘密。

Consider an example where an API_KEY is stored as a secret:

考虑以下示例,其中 API_KEY 被存储为一个秘密:

To generate a pair of cryptographic keys you can run the following command. The private key file is highly sensitive and it shouldn't be committed in a repository.

要生成一对加密密钥,您可以运行以下命令。私钥文件非常敏感,它不应该被提交到仓库中。

bin/console secrets:generate-keys

This command will generate a file for the API_KEY secret in config/secrets/env(dev|prod|etc.)

此命令将在config/secrets/env(dev|prod|etc.)中生成API_KEY密钥文件

bin/console secret:set API_KEY

You can access secret values in your code in the same manner as environment variables. It's very important to note that if there are environment variables and secrets with identical names, the values from environment variables will always override secrets.

您可以通过与环境变量相同的方式在代码中访问密钥值。请注意,如果存在同名环境变量和密钥,环境变量的值将始终覆盖密钥

For more details refer to Symfony Secrets Documentation.

有关详细信息,请参阅Symfony密钥文档

Summary / 总结

  • Make sure your app is not in debug mode while in production. To turn off debug mode, set your APP_ENV environment variable to prod:
    中文:在生产环境中,请确保您的应用程序不在调试模式。要关闭调试模式,请将APP_ENV环境变量设置为prod

    APP_ENV=prod
    
  • Make sure your PHP configuration is secure. You may refer to the PHP Configuration Cheat Sheet for more information on secure PHP configuration settings.
    中文:请确保您的PHP配置安全。您可以通过PHP配置速查表获取有关安全PHP配置设置的更多信息

  • Ensure that the SSL certificate is properly configured in your web server and configure it to enforce HTTPS by redirecting HTTP traffic to HTTPS.
    中文:确保您的Web服务器中SSL证书配置正确,并配置它通过将HTTP流量重定向到HTTPS来强制执行HTTPS

  • Implement security headers to enhance the security posture of your application.
    中文:实现安全头以增强应用程序的安全态势

  • Ensure that file and directory permissions are set correctly to minimize security risks.
    中文:确保文件和目录权限设置正确,以最大限度地减少安全风险

  • Implement regular backups of your production database and critical files. Have a recovery plan in place to quickly restore your application in case of any issues.
    中文:实施生产数据库和关键文件的定期备份。制定恢复计划,以便在出现任何问题时快速恢复应用程序。

  • Use security checkers to scan your dependencies to identify known vulnerabilities.
    中文:使用安全检查器扫描依赖项以识别已知漏洞。

  • Consider setting up monitoring tools and error reporting mechanisms to quickly identify and address issues in your production environment. Explore tools like Blackfire.io.
    中文:考虑设置监控工具和错误报告机制,以便快速识别和解决生产环境中的问题。探索类似 Blackfire.io 的工具。

References / 参考