跳到内容

NelmioSecurityBundle

编辑此页

NelmioSecurityBundle 为您的 Symfony 应用程序提供额外的安全功能。

安装

在您的 composer.json 文件中要求 nelmio/security-bundle 包并更新您的依赖项

1
$ composer require nelmio/security-bundle

该扩展包应该会被 Symfony Flex 自动启用。如果您不使用 Flex,您需要通过在项目的 config/bundles.php 文件中添加以下行来手动启用该扩展包

1
2
3
4
5
6
7
8
<?php
// config/bundles.php

return [
    // ...
    Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true],
    // ...
];

如果您的项目中没有 config/bundles.php 文件,则说明您正在使用较旧的 Symfony 版本。在这种情况下,您应该有一个 app/AppKernel.php 文件。编辑该文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = [
            // ...

            new Nelmio\SecurityBundle\NelmioSecurityBundle(),
        ];

        // ...
    }

    // ...
}

功能特性

  • 内容安全策略:跨站脚本攻击 (XSS) 可以通过现代浏览器中使用策略来缓解,该策略指示浏览器永远不要执行内联脚本,或者永远不要从页面域以外的其他域加载内容。
  • 签名 Cookie:指定要签名的某些 Cookie,以便用户无法修改它们。请注意,它们不会被加密,而是仅被签名。内容对用户仍然可见。
  • 点击劫持保护:X-Frame-Options 标头被添加到所有响应中,以防止您的站点被放入 frame/iframe 中。这可能会产生严重的安全隐患,正如 Facebook 和其他公司一次又一次证明的那样。您可以允许从站点自身或从任何地方按 URL 为单位进行站点框架。
  • 外部重定向检测:基于用户输入将您的站点重定向到任意 URL 可能会被利用,从而使用户误以为点击的链接指向有效站点,而实际上它们指向恶意内容。也可能通过这种方式获得 PageRank。
  • 强制 HTTPS/SSL 处理:这将强制所有请求都通过 SSL。它还会发送 HSTS 标头,以便支持它的现代浏览器可以使即使输入不带 https 的 URL 的用户也使用 HTTPS,从而避免在公共 Wi-Fi 上受到攻击。
  • 灵活的 HTTPS/SSL 处理:如果您不想强制所有用户都使用 HTTPS,您至少应该对已登录用户使用安全会话 Cookie 并强制 SSL。但是,当已登录用户访问非 HTTPS 资源时,他们会显示为已注销。这不是一个真正好的解决方案。这将使应用程序检测到已登录的用户并将他们重定向到安全 URL,而不会使会话 Cookie 不安全。
  • 禁用内容类型嗅探:要求使用正确的多用途互联网邮件扩展类型加载脚本。这将禁用某些浏览器具有的功能,该功能使用内容嗅探来确定响应是否为有效的脚本文件。
  • (已弃用) XSS 保护:在兼容的浏览器(IE 8 及更高版本)上启用/禁用 Microsoft XSS 保护。
  • 引用站点策略Referrer-Policy 标头被添加到所有响应中,以控制添加到从您的站点发出的请求以及浏览器离开您的站点的导航的 Referer 标头。

最大安全配置

这是提供最大安全保护的配置,但您应该阅读下一节以获得详细的建议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# config/packages/nelmio_security.yaml
nelmio_security:
    # signs/verifies all cookies
    signed_cookie:
        names: ['*']
    # prevents framing of the entire site
    clickjacking:
        paths:
            '^/.*': DENY
        hosts:
            - '^foo\.com$'
            - '\.example\.org$'

    # prevents redirections outside the website's domain
    external_redirects:
        abort: true
        log: true

    # prevents inline scripts, unsafe eval, external scripts/images/styles/frames, etc
    csp:
        hosts: []
        content_types: []
        enforce:
            level1_fallback: false
            browser_adaptive:
                enabled: false
            report-uri: '%router.request_context.base_url%/nelmio/csp/report'
            default-src:
                - 'none'
            script-src:
                - 'self'
            block-all-mixed-content: true # defaults to false, blocks HTTP content over HTTPS transport
            # upgrade-insecure-requests: true # defaults to false, upgrades HTTP requests to HTTPS transport

    # disables content type sniffing for script resources
    content_type:
        nosniff: true

    # Send a full URL in the ``Referer`` header when performing a same-origin request,
    # only send the origin of the document to secure destination (HTTPS->HTTPS),
    # and send no header to a less secure destination (HTTPS->HTTP).
    # If ``strict-origin-when-cross-origin`` is not supported, use ``no-referrer`` policy,
    # no referrer information is sent along with requests.
    referrer_policy:
        enabled: true
        policies:
            - 'no-referrer'
            - 'strict-origin-when-cross-origin'

    # forces HTTPS handling, don't combine with flexible mode
    # and make sure you have SSL working on your site before enabling this
#    forced_ssl:
#        hsts_max_age: 2592000 # 30 days
#        hsts_subdomains: true
#        redirect_status_code: 302 # default, switch to 301 for permanent redirects

    # flexible HTTPS handling, read the detailed config info
    # and make sure you have SSL working on your site before enabling this
#    flexible_ssl:
#        cookie_name: auth
#        unsecured_logout: false

内容安全策略 (CSP)

使用 CSP,您可以设置现代浏览器理解并将遵守的策略。该策略包含许多不同的指令;default-srcscript-srcobject-srcstyle-srcimg-srcmedia-srcframe-srcfont-srcconnect-srcbase-urichild-srcform-actionframe-ancestorsplugin-typesblock-all-mixed-contentupgrade-insecure-requestsreport-urimanifest-src

您可以为每种内容类型提供指令数组,但 block-all-mixed-contentupgrade-insecure-requests 除外,它们仅接受布尔值。空内容类型将从 default-src 继承,指定的内容类型永远不会从 default-src 继承。有关详细信息,请参阅 内容安全策略 1.0内容安全策略 2.0 规范。

每个指令都应该是域、URI 或关键字。关键字 'self' 将允许来自与页面相同来源的内容。如果您需要允许内联脚本或 eval(),您可以使用 'unsafe-inline''unsafe-eval'

注意

通过使用 'unsafe-inline''unsafe-eval',您实际上禁用了 CSP 的 XSS 保护机制。

除了内容类型外,该策略还接受 report-uri,它应该是浏览器可以在其中 POST JSON 负载 的 URI,以在违反策略指令时。从 v3.5 开始,也可以包含 report-to 指令来配置报告端点(请参阅 Reporting API),该指令旨在取代已弃用的 report-uri 指令。

可选的 content_types 键允许您仅在某些 HTTP 响应(给定其内容类型)上限制内容安全策略标头。

最后,可选的 hosts 键允许您配置应在其上强制执行 CSP 规则的主机名(例如,foo.example.org)。如果列表为空(默认情况下为空),则所有主机名都将使用 CSP 规则。

如果 content_typeshosts 选项不符合您的需求,您还可以配置一个实现 Symfony\Component\HttpFoundation\RequestMatcherInterface 的服务作为 request_matcher。然后,不再使用 content_typeshosts 选项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        enabled: true
        report_logger_service: logger
        request_matcher: null
        hosts: []
        content_types: []
        enforce:
            # see full description below
            level1_fallback: true
            # only send directives supported by the browser, defaults to false
            # this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
            browser_adaptive:
                enabled: false
            report-uri: '%router.request_context.base_url%/nelmio/csp/report'
            default-src: [ 'self' ]
            frame-src: [ 'https://www.youtube.com' ]
            script-src:
                - 'self'
                - 'unsafe-inline'
            img-src:
                - 'self'
                - facebook.com
                - flickr.com
            block-all-mixed-content: true # defaults to false, blocks HTTP content over HTTPS transport
            # upgrade-insecure-requests: true # defaults to false, upgrades HTTP requests to HTTPS transport
        report:
            # see full description below
            level1_fallback: true
            # only send directives supported by the browser, defaults to false
            # this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
            browser_adaptive:
                enabled: true
            report-uri: '%router.request_context.base_url%/nelmio/csp/report'
            script-src:
                - 'self'

以上配置将强制执行以下策略

  • 默认情况下允许来自与页面相同来源的内容
  • 框架仅来自安全的 YouTube 连接
  • JavaScript 来自相同来源和内联 <script> 标签
  • 图像来自相同来源、facebook.comflickr.com

任何违反强制策略的行为都将发布到 /nelmio/csp/report

此外,该配置仅报告但不强制执行 JavaScript 只能从同一服务器执行的策略。

该扩展包提供了默认的报告实现,该实现将违规记录为默认记录器的通知,要启用,请将以下内容添加到您的 routing.yml

1
2
3
4
5
# config/routing.yaml
nelmio_security:
    path:     /nelmio/csp/report
    defaults: { _controller: nelmio_security.csp_reporter_controller::indexAction }
    methods:  [POST]

(可选)使用 report_logger_service 记录到 'security' 频道

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        report_logger_service: monolog.logger.security

(可选)禁用 compat_headers 以避免发送 X-Content-Security-Policy (IE10、IE11、Firefox < 23)。这将意味着这些浏览器没有 CSP 指令。

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        compat_headers: false

使用浏览器自适应指令

可以将 NelmioSecurityBundle 配置为仅发送浏览器可以理解的指令。这减少了通过 report URI 提供的噪声。这是对 Twitter SecureHeaders 库 中所做工作的直接移植。

使用 enabled 键启用它

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        enforce:
            browser_adaptive:
                enabled: true

注意

这将解析用户代理,并可能消耗一些 CPU 使用率。您可以指定缓存的解析器以避免消耗过多的 CPU

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        enforce:
            browser_adaptive:
                enabled: true
                parser: my_own_parser

并基于 NelmioSecurityBundle 提供的缓存解析器之一或您自己的解析器声明服务 my_own_parser。例如,使用 PsrCacheUAFamilyParser

1
2
3
4
5
<service id="my_own_parser" class="Nelmio\SecurityBundle\UserAgent\UAFamilyParser\PsrCacheUAFamilyParser">
  <argument type="service" id="app.my_cache.pool"/>
  <argument type="service" id="nelmio_security.ua_parser.ua_php"/>
  <argument>604800</argument>
</service>

Nelmio\SecurityBundle\UserAgent\UAFamilyParser 中查找这些解析器。

内联脚本处理的消息摘要

如果您想在 script-srcstyle-src 上禁用 'unsafe-inline'(推荐),Nelmio Security Bundle 开箱即用地提供了消息摘要功能。Twig 原生支持。

您可以在配置中配置用于消息摘要的算法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        hash:
            algorithm: sha512 # default is sha256, available are sha256, sha384 and sha512
        enforce:
            # Provides compatibility with CSP level 1 (old / non-yet-compatible browsers) when using CSP level 2
            # features likes hash and nonce. It adds a 'unsafe-inline' source to a directive whenever a nonce or hash
            # is used.
            # From RFC: " If 'unsafe-inline' is not in the list of allowed style sources, or if at least one
            #             nonce-source or hash-source is present in the list of allowed style sources "
            # See https://www.w3.org/TR/CSP2/#directive-style-src and https://www.w3.org/TR/CSP2/#directive-script-src
            level1_fallback: true
            default-src: ['self']

在您的 Twig 模板中使用 cspscriptcspstyle 标签来自动计算消息摘要并将其插入到您的标头中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% cspscript %}
<script>
    window.api_key = '{{ api_key }}';
</script>
{% endcspscript %}

{# ... #}

{% cspstyle %}
<style>
    body {
        background-color: '{{ bgColor }}';
    }
</style>
{% endcspstyle %}

如果您不使用 Twig,则可以将消息摘要与 ContentSecurityPolicyListener 一起使用,它将自动计算消息摘要并将其添加到响应 CSP 标头

1
2
3
4
5
6
7
8
9
10
$listener->addScript("<script>
    window.api_key = '{{ api_key }}';
</script>");


$listener->addStyle("<style>
    body {
        background-color: '{{ bgColor }}';
    }
</style>");

内联脚本处理的 Nonce

内容安全策略规范还提出了用于内联的 nonce 实现。Nelmio Security Bundle 开箱即用地提供了 nonce 功能。Twig 原生支持。

在您的 Twig 模板中使用 csp_nonce 函数来访问当前请求的 nonce 并将其添加到响应 CSP 标头。如果您不请求 nonce,则不会生成 nonce。

1
2
3
4
5
6
7
8
9
10
11
<script nonce="{{ csp_nonce('script') }}">
    window.api_key = '{{ api_key }}';
</script>

{# ... #}

<style nonce="{{ csp_nonce('style') }}">
    body {
        background-color: '{{ bgColor }}';
    }
</style>

如果您不使用 Twig,则可以将 nonce 功能与 ContentSecurityPolicyListener 一起使用

1
2
3
4
// generates a nonce at first time, returns the same nonce once generated
$listener->getNonce('script');
// or
$listener->getNonce('style');

报告

使用 report-uri,您可以轻松地使用 ContentSecurityPolicyController 收集违规行为。这是一个使用 routing.yml 的配置示例

1
2
3
4
5
# config/routes.yaml
csp_report:
    path: /csp/report
    methods: [POST]
    defaults: { _controller: nelmio_security.csp_reporter_controller::indexAction }

配置的这一部分有助于过滤此端点收集的噪声

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        report_endpoint:
            log_level: "notice" # Use the appropriate log_level
            log_formatter: ~    # Declare a service name that must implement Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Log\LogFormatterInterface
            log_channel: ~      # Declare the channel to use with the logger
            filters:
                # Filter false positive reports given a domain list
                domains: true
                # Filter false positive reports given a scheme list
                schemes: true
                # Filter false positive reports given known browser bugs
                browser_bugs: true
                # Filter false positive reports given known injected scripts
                injected_scripts: true
                # You can add you custom filter rules by implementing Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Filter\NoiseDetectorInterface
                # and tag the service with "nelmio_security.csp_report_filter"
            dismiss:
                # A list of key-values that should be dismissed
                # A key is either a domain or a regular expression
                # A value is a source or an array of source. The '*' wilcard is accepted
                '/^data:/': 'script-src'
                '/^https?:\/\/\d+\.\d+\.\d+\.\d+(:\d+)*/': '*'
                'maxcdn.bootstrapcdn.com': '*'
                'www.gstatic.com': ['media-src', 'img-src']

签名 Cookie

理想情况下,您应该显式指定要签名的 Cookie。这样做的原因很简单。Cookie 随每个请求一起发送。签名通常比 Cookie 值本身长,因此签名所有内容只会不必要地减慢您的应用程序速度并增加用户的带宽使用量。

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    signed_cookie:
        names: [test1, test2]

但是,为了简单起见,并从高安全性开始并在以后进行优化,您可以将 * 指定为 Cookie 名称,以自动签名所有 Cookie。

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    signed_cookie:
        names: ['*']

其他可选配置设置

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    signed_cookie:
        secret: this_is_very_secret # defaults to global %secret% parameter
        hash_algo: sha512 # defaults to sha256, see ``hash_algos()`` for available algorithms

升级哈希算法

随着计算能力和安全研究的进步,升级到更安全的哈希算法对于维护应用程序安全至关重要。但是,仅仅更改 `hash_algo` 值可能会破坏现有的 Cookie。为了方便平稳过渡,此扩展包提供了 `legacy_hash_algo` 选项。如果您的应用程序当前使用 `sha-256` 并且您希望升级到更安全的 `sha3-256` 算法,请将 `legacy_hash_algo` 设置为 `sha256`,并将 `hash_algo` 设置为 `sha3-256`。

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    signed_cookie:
        hash_algo: sha3-256
        legacy_hash_algo: sha256

注意

`legacy_hash_algo` 选项可能会使您的应用程序容易受到降级攻击,并且应仅临时用于向后兼容。

点击劫持保护

大多数网站不使用框架,也不需要可框架化。这是一个常见的攻击媒介,所有当前的浏览器(IE8+、Opera10.5+、Safari4+、Chrome4+ 和 Firefox3.7+)都有解决方案。您的站点发送的额外标头将告诉浏览器无法在框架中显示它。浏览器会通过显示简短的解释而不是内容或空白页来做出反应。

X-Frame-Options 标头的有效值是 DENY(阻止所有页面的框架)和 SAMEORIGIN(阻止来自非同一域的所有页面的框架)。此外,如果您想允许少量 URL,然后拒绝其他所有内容,则此扩展包还支持 ALLOW 选项,该选项会跳过为匹配的 URL 创建标头。

还有一个选项,截至目前 支持不佳,是使用 ALLOW-FROM uri,其中 uri 可以是任何来源 URL,从 example.orghttps://example.org:123/sub/path。如果您有多个域设置,这使您可以准确指定哪个域可以嵌入您的站点。

默认配置(拒绝所有内容)

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    clickjacking:
        paths:
            '^/.*': DENY
        content_types: []
        hosts: []

允许列表配置(拒绝除少量 URL 之外的所有内容)

1
2
3
4
5
6
7
8
9
10
# config/packages/nelmio_security.yaml
nelmio_security:
    clickjacking:
        paths:
            '^/iframes/': ALLOW
            '^/business/': 'ALLOW-FROM https://biz.example.org'
            '^/local/': SAMEORIGIN
            '^/.*': DENY
        content_types: []
        hosts: []

应用于某些主机

1
2
3
4
5
6
7
8
9
10
# config/packages/nelmio_security.yaml
nelmio_security:
    clickjacking:
        paths:
            '^/iframes/': ALLOW
            '^/.*': DENY
        content_types: []
        hosts:
            - '^foo\.com$'
            - '\.example\.org$'

当然,您也可以只拒绝一些关键 URL,而让其余的保持不变

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    clickjacking:
        paths:
            '^/message/write': DENY
        content_types: []
        hosts: []

可选的 content_types 键允许您仅在某些 HTTP 响应(给定其内容类型)上限制 X-Frame-Options 标头。

外部重定向检测

此功能可帮助您检测和防止重定向到外部站点。如果您不小心将查询参数用作重定向目标,则很容易发生这种情况。

您可以通过启用日志记录来记录这些内容(以警告级别记录)

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        log: true

您可以中止重定向(它们将被 403 响应替换)

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        abort: true

或者您可以覆盖它们,将重定向的 Location 标头替换为路由名称或另一个 URL

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        # redirect to the 'home' route
        override: home
        # use this to redirect to another URL
        # override: /foo

如果您想在覆盖页面上显示被阻止的 URL,您可以指定 forward_as 参数,该参数定义哪个查询参数将接收 URL。例如,使用下面的配置,重定向到 http://example.org/ 将被覆盖为 /external-redirect?redirUrl=http://example.org/

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        # redirect and forward the overridden URL
        override: /external-redirect
        forward_as: redirUrl

由于出于合法原因(通常是 OAuth 登录等)必须重定向到网站外部是很常见的,因此您可以允许几个域名。它们的所有子域也将被允许,因此如果需要,您可以允许您自己网站的子域。

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        abort: true
        allow_list:
            - twitter.com
            - facebook.com

如果您有一个可以重定向到另一个主机的控制器,您还可以使用 `ExternalRedirectResponse` 来允许重定向,而无需全局配置主机。传递给 `ExternalRedirectResponse` 的任何主机都将添加到已全局配置的主机之外。

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        abort: true
        allow_list:
            - bar.com
1
2
3
4
5
6
7
8
9
10
use Nelmio\SecurityBundle\ExternalRedirect\ExternalRedirectResponse;

// Will be allowed even though "foo.com" is not allowed globally through the config.
return new ExternalRedirectResponse('https://foo.com', ['foo.com', 'auth-provider.test']);

// Will not be allowed.
return new ExternalRedirectResponse('https://not-allowed.com', ['foo.com', 'auth-provider.test']);

// Will be allowed because "bar.com" is allowed globally through the config.
return new ExternalRedirectResponse('https://bar.com', ['foo.com', 'auth-provider.test']);

强制 HTTPS/SSL 处理

默认情况下,此选项始终强制您的整个站点使用 SSL。它会将所有使用 http:// URL 访问该站点的用户重定向到具有 302 响应的 https:// URL。

此功能的基本配置如下

1
2
3
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl: ~

如果您启用此选项,建议您还将您的会话 Cookie 设置为安全,以及您发送的所有其他 Cookie。您可以使用以下方法执行前者

1
2
3
4
# config/packages/framework.yaml
framework:
    session:
        cookie_secure: true

要防止少量 URL 被强制重定向到 SSL,您可以定义一个允许的正则表达式列表

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        enabled: true
        allow_list:
            - ^/unsecure/

要将强制重定向限制为仅某些主机名,您可以定义主机名列表作为正则表达式

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        enabled: true
        hosts:
            - ^\.example\.org$

要更改重定向的方式(例如永久重定向),您可以设置

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        enabled: true
        redirect_status_code: 301

然后,如果您想进一步推动它,您可以启用 HTTP 严格传输安全 (HSTS)。这基本上是发送一个标头来告诉浏览器您的站点必须始终使用 SSL 访问。如果用户输入 http:// URL,浏览器会自动将其转换为 https://,并且会在发出任何请求之前执行此操作,从而防止中间人攻击。

浏览器将缓存指定 hsts_max_age(以秒为单位)的值,如果您启用 hsts_subdomains 选项,该行为也将应用于所有子域。

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        hsts_max_age: 2592000 # 30 days
        hsts_subdomains: true

您还可以通过启用 hsts_preload 来告诉浏览器将您的站点添加到已知的 HSTS 站点列表中。一旦您的站点出现在 Chrome 和 Firefox 预加载列表中,那么访问您站点的新用户将被自动重定向到 HTTPS URL。

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        hsts_max_age: 31536000 # 1 year
        hsts_preload: true

注意

目前 Chrome 要求Firefox 也要求 至少 1 年的值。hsts_subdomains 也必须启用才能进行预加载。

您可以通过将您的站点提交到 HSTS 预加载列表 来加快包含过程。

一个小小的警告:虽然 HSTS 对于安全性非常有用,但这意味着如果浏览器无法确定您的 SSL 证书有效,它将不允许用户查询您的站点。这只是意味着您应该小心并在到期时及时续订您的证书。

提示

查看 我可以使用 HSTS 吗? 以获取有关其在浏览器中支持的完整信息。

灵活的 HTTPS/SSL 处理

安全处理 SSL 的最佳方法是为您的整个站点启用它。

但是在某些情况下,这并不理想,无论是出于缓存或性能原因,还是仅仅因为您网站的大多数访问者都是匿名的,并且从 SSL 增加的隐私和安全性中受益不多。

如果您不想全面启用 SSL,则需要避免不安全网络(通常是开放 Wi-Fi)上的人们通过以非加密方式发送会话 Cookie 来窃取他们的会话 Cookie。实现此目的的方法是将您的会话 Cookie 设置为安全 - 但现在不要这样做,请继续阅读到最后。

1
2
3
4
# config/packages/framework.yaml
framework:
    session:
        cookie_secure: true

如果您使用“记住我”功能,您也会将该功能标记为安全

1
2
3
4
5
6
# config/packages/security.yaml
security:
    firewalls:
        somename:
            remember_me:
                secure: true

现在,如果您这样做,您有两个问题。首先,不安全的页面将无法再使用会话,这可能很不方便。其次,如果已登录的用户访问您网站的非 HTTPS 页面,则会被视为匿名,因为他的浏览器不会发送会话 Cookie。为了解决这个问题,此扩展包在用户登录后设置一个新的不安全 Cookie(flexible_ssl.cookie_name,默认为 auth)。这样,如果任何页面被已登录的用户以不安全的方式访问,他将被重定向到页面的安全版本,并且他的会话随后对框架可见。

启用 NelmioSecurityBundle 的 flexible_ssl 选项将确保已登录的用户始终看到安全页面,并确保他们的会话 Cookie 是安全的,但是匿名用户仍然能够拥有不安全的会话,如果您需要使用它来存储非关键数据,例如语言设置等等。“记住我” Cookie 也将始终安全,即使您将设置保留为 false。

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    flexible_ssl:
        cookie_name: auth
        unsecured_logout: false

您还需要在安全配置中配置一件事:每个防火墙都应该添加我们的注销监听器,以便在用户注销时清除特殊的 auth Cookie。您可以这样做:

1
2
3
4
5
6
7
8
# config/packages/security.yaml
security:
    firewalls:
        somename:
            # ...
            logout:
                handlers:
                    - nelmio_security.flexible_ssl_listener

在注销时,如果您希望用户重定向到不安全的页面,请将 unsecured_logout 设置为 true。

内容类型嗅探

禁用脚本资源的内容类型嗅探。强制浏览器仅执行具有有效内容类型标头的脚本文件。这需要使用 来自 Microsoft 的非标准 nosniff 标头

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    content_type:
        nosniff: true

XSS 保护 (已弃用)

注意

此功能是非标准的,并且已弃用。建议改用 CSP:http://mdn.org.cn/en-US/docs/Web/HTTP/Headers/X-XSS-Protection

在兼容的浏览器上启用或禁用 Microsoft XSS Protection。这需要使用 来自 Microsoft 的非标准 X-XSS-Protection 标头

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    xss_protection:
        enabled: true
        mode_block: true
        report_uri: '%router.request_context.base_url%/nelmio/xss/report'

引用站点策略

添加 Referrer-Policy 标头来控制添加到从您的站点发出的请求以及浏览器离开您的站点的导航的 Referer 标头。

您可以指定多个 referrer 策略。策略的顺序很重要。浏览器将仅选择他们理解的最后一个策略。例如,旧版本的浏览器不理解 strict-origin-when-cross-origin 策略。网站可以指定一个 no-referrer 策略,后跟一个 strict-origin-when-cross-origin 策略:旧版本的浏览器将忽略未知的 strict-origin-when-cross-origin 值并使用 no-referrer,而新版本的浏览器将使用 strict-origin-when-cross-origin,因为它是最后一个被处理的策略。

以下是有效的 referrer 策略

为了更好地保护您的网站安全,请使用 no-referrersame-originstrict-originstrict-origin-when-cross-origin

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    referrer_policy:
        enabled: true
        policies:
            - 'no-referrer'
            - 'strict-origin-when-cross-origin'
本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本