8000 Merge branch '2.7' into 2.8 · symfony/symfony-docs@52f14f8 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 52f14f8

Browse files
committed
Merge branch '2.7' into 2.8
* 2.7: Hash nonce when using as file name File System Security Issue in Custom Auth Article [Cookbook] Tweaking registration_form (e.g. bcrypt)
2 parents 1d1ec81 + 319998d commit 52f14f8

File tree

2 files changed

+70
-16
lines changed

2 files changed

+70
-16
lines changed

cookbook/doctrine/registration_form.rst

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
.. index::
22
single: Doctrine; Simple Registration Form
33
single: Form; Simple Registration Form
4+
single: Security; Simple Registration Form
45

5-
How to Implement a simple Registration Form
6+
How to Implement a Simple Registration Form
67
===========================================
78

89
Creating a registration form is pretty easy - it *really* means just creating
9-
a form that will update some ``User`` model object (a Doctrine entity in this example)
10-
and then save it.
10+
a form that will update some ``User`` model object (a Doctrine entity in this
11+
example) and then save it.
1112

1213
.. tip::
1314

14-
The popular `FOSUserBundle`_ provides a registration form, reset password form
15-
and other user management functionality.
15+
The popular `FOSUserBundle`_ provides a registration form, reset password
16+
form and other user management functionality.
1617

1718
If you don't already have a ``User`` entity and a working login system,
1819
first start with :doc:`/cookbook/security/entity_provider`.
@@ -61,27 +62,27 @@ With some validation added, your class may look something like this::
6162
private $id;
6263

6364
/**
64-
* @ORM\Column(type="string", length=255)
65+
* @ORM\Column(type="string", length=255, unique=true)
6566
* @Assert\NotBlank()
6667
* @Assert\Email()
6768
*/
6869
private $email;
6970

7071
/**
71-
* @ORM\Column(type="string", length=255)
72+
* @ORM\Column(type="string", length=255, unique=true)
7273
* @Assert\NotBlank()
7374
*/
7475
private $username;
7576

7677
/**
7778
* @Assert\NotBlank()
78-
* @Assert\Length(max = 4096)
79+
* @Assert\Length(max=4096)
7980
*/
8081
private $plainPassword;
8182

8283
/**
8384
* The below length depends on the "algorithm" you use for encoding
84-
* the password, but this works well with bcrypt
85+
* the password, but this works well with bcrypt.
8586
*
8687
* @ORM\Column(type="string", length=64)
8788
*/
@@ -124,6 +125,13 @@ With some validation added, your class may look something like this::
124125
$this->password = $password;
125126
}
126127

128+
public function getSalt()
129+
{
130+
// The bcrypt algorithm don't require a separate salt.
131+
// You *may* need a real salt if you choose a different encoder.
132+
return null;
133+
}
134+
127135
// other methods, including security methods like getRoles()
128136
}
129137

@@ -146,8 +154,10 @@ example, see the :ref:`Entity Provider <security-crete-user-entity>` article.
146154
only place where you don't need to worry about this is your login form,
147155
since Symfony's Security component handles this for you.
148156

149-
Create a Form for the Model
150-
---------------------------
157+
.. _create-a-form-for-the-model:
158+
159+
Create a Form for the Entity
160+
----------------------------
151161

152162
Next, create the form for the ``User`` entity::
153163

@@ -195,8 +205,9 @@ There are just three fields: ``email``, ``username`` and ``plainPassword``
195205
Handling the Form Submission
196206
----------------------------
197207

198-
Next, you need a controller to handle the form. Start by creating a simple
199-
controller for displaying the registration form::
208+
Next, you need a controller to handle the form rendering and submission. If the
209+
form is submitted, the controller performs the validation and saves the data
210+
into the database::
200211

201212
// src/AppBundle/Controller/RegistrationController.php
202213
namespace AppBundle\Controller;
@@ -222,6 +233,7 @@ controller for displaying the registration form::
222233
// 2) handle the submit (will only happen on POST)
223234
$form->handleRequest($request);
224235
if ($form->isSubmitted() && $form->isValid()) {
236+
225237
// 3) Encode the password (you could also do this via Doctrine listener)
226238
$password = $this->get('security.password_encoder')
227239
->encodePassword($user, $user->getPlainPassword());
@@ -245,6 +257,45 @@ controller for displaying the registration form::
245257
}
246258
}
247259

260+
To define the algorithm used to encode the password in step 3 configure the
261+
encoder in the security configuration:
262+
263+
.. configuration-block::
264+
265+
.. code-block:: yaml
266+
267+
# app/config/security.yml
268+
security:
269+
encoders:
270+
AppBundle\Entity\User: bcrypt
271+
272+
.. code-block:: xml
273+
274+
<!-- app/config/security.xml -->
275+
<?xml version="1.0" charset="UTF-8" ?>
276+
<srv:container xmlns="http://symfony.com/schema/dic/security F438 "
277+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
278+
xmlns:srv="http://symfony.com/schema/dic/services"
279+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
280+
281+
<config>
282+
<encoder class="AppBundle\Entity\User">bcrypt</encoder>
283+
</config>
284+
</srv:container>
285+
286+
.. code-block:: php
287+
288+
// app/config/security.php
289+
$container->loadFromExtension('security', array(
290+
'encoders' => array(
291+
'AppBundle\Entity\User' => 'bcrypt',
292+
),
293+
));
294+
295+
In this case the recommended ``bcrypt`` algorithm is used. To learn more
296+
about how to encode the users password have a look into the
297+
:ref:`security chapter <book-security-encoding-user-password>`.
298+
248299
.. note::
249300

250301
If you decide to NOT use annotation routing (shown above), then you'll

cookbook/security/custom_authentication_provider.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ set an authenticated token in the token storage if successful.
135135
{
136136
$request = $event->getRequest();
137137
138-
$wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/';
138+
$wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([a-zA-Z0-9+/]+={0,2})", Created="([^"]+)"/';
139139
if (!$request->headers->has('x-wsse') || 1 !== preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches)) {
140140
return;
141141
}
@@ -260,14 +260,17 @@ the ``PasswordDigest`` header value matches with the user's password.
260260
261261
// Validate that the nonce is *not* used in the last 5 minutes
262262
// if it has, this could be a replay attack
263-
if (file_exists($this->cacheDir.'/'.$nonce) && file_get_contents($this->cacheDir.'/'.$nonce) + 300 > time()) {
263+
if (
264+
file_exists($this->cacheDir.'/'.md5($nonce))
265+
&& file_get_contents($this->cacheDir.'/'.md5($nonce)) + 300 > time()
266+
) {
264267
throw new NonceExpiredException('Previously used nonce detected');
265268
}
266269
// If cache directory does not exist we create it
267270
if (!is_dir($this->cacheDir)) {
268271
mkdir($this->cacheDir, 0777, true);
269272
}
270-
file_put_contents($this->cacheDir.'/'.$nonce, time());
273+
file_put_contents($this->cacheDir.'/'.md5($nonce), time());
271274
272275
// Validate Secret
273276
$expected = base64_encode(sha1(base64_decode($nonce).$created.$secret, true));

0 commit comments

Comments
 (0)
0