使用CSRF保护登录表单
当使用登录表单时,你应该确保针对CSRF (Cross-site request forgery) 进行了防护。Security组件已经内置了对CSRF的支持。在本文中,你将学习如何在登录表单使用它。
登录过程的CSRF攻击不怎么出名。如果你对此好奇,可参考 伪造登录请求。
配置CSRF防护 ¶
首先,配置Security组件,令CSRF防护可用。Security组件需要一个 CSRF token provider。你可以把这个值设为Security组件中的默认provider:
|
# app/config/security.yml
security:
# ...
firewalls:
secured_area:
# ...
form_login:
# ...
csrf_token_generator: security.csrf.token_manager |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<!-- app/config/security.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<srv:container xmlns="Http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<config>
<!-- ... -->
<firewall name="secured_area">
<!-- ... -->
<form-login csrf-token-generator="security.csrf.token_manager" />
</firewall>
</config>
</srv:container> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// app/config/security.php
$container->loadFromExtension('security', array(
// ...
'firewalls' => array(
'secured_area' => array(
// ...
'form_login' => array(
// ...
'csrf_token_generator' => 'security.csrf.token_manager',
),
),
),
)); |
Security组件还可以被进一步配置,但是在登录表单使用CSRF时的全部信息都在这里了。
输出CSRF字段 ¶
现在,Security组件将要检查CSRF token,你需要在登录表单中添加一个隐藏的CSRF token字段。默认时,字段的名称是 _csrf_token
。该隐藏字段必须要包含CSRF token,它可通过 csrf_token
函数生成。此函数需要一个token ID,当使用此登录表单时必须将其设为 authenticate
:
1
2
3
4
5
6
7
8
9
10
11
12
|
{# src/AppBundle/Resources/views/Security/login.HTML.twig #}
{# ... #}
<form action="{{ path('login') }}" method="post">
{# ... the login fields / 表单登录的字段 #}
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
<button type="submit">login</button>
</form> |
1
2
3
4
5
6
7
8
9
10
11
12
|
<!-- src/AppBundle/Resources/views/Security/login.html.php -->
<!-- ... -->
<form action="<?php echo $view['router']->path('login') ?>" method="post">
<!-- ... the login fields -->
<input type="hidden" name="_csrf_token"
value="<?php echo $view['form']->csrfToken('authenticate') ?>"
>
<button type="submit">login</button>
</form> |
此后,你已经可以针对CSRF攻击来保护你的表单了。
通过设置配置文件中的 csrf_parameter
你可以改变字段名称。而改变 token ID 则需要设置 csrf_token_id
:
|
# app/config/security.yml
security:
# ...
firewalls:
secured_area:
# ...
form_login:
# ...
csrf_parameter: _csrf_security_token
csrf_token_id: a_private_string |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<!-- app/config/security.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<config>
<!-- ... -->
<firewall name="secured_area">
<!-- ... -->
<form-login csrf-parameter="_csrf_security_token"
csrf-token-id="a_private_string"
/>
</firewall>
</config>
</srv:container> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// app/config/security.php
$container->loadFromExtension('security', array(
// ...
'firewalls' => array(
'secured_area' => array(
// ...
'form_login' => array(
// ...
'csrf_parameter' => '_csrf_security_token',
'csrf_token_id' => 'a_private_string'
),
),
),
)); |