Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit1567041

Browse files
wouterjchalasr
authored andcommitted
[Security] Rework the remember me system
1 parent0f96ac7 commit1567041

File tree

68 files changed

+2240
-505
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+2240
-505
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Bridge\Doctrine\SchemaListener;
13+
14+
useDoctrine\Common\EventSubscriber;
15+
useDoctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
16+
useDoctrine\ORM\Tools\ToolEvents;
17+
useSymfony\Bridge\Doctrine\Security\RememberMe\DoctrineTokenProvider;
18+
useSymfony\Component\Security\Http\RememberMe\PersistentRememberMeHandler;
19+
useSymfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface;
20+
21+
/**
22+
* Automatically adds the rememberme table needed for the {@see DoctrineTokenProvider}.
23+
*
24+
* @author Wouter de Jong <wouter@wouterj.nl>
25+
*/
26+
finalclass RememberMeTokenProviderDoctrineSchemaSubscriberimplements EventSubscriber
27+
{
28+
private$rememberMeHandlers;
29+
30+
/**
31+
* @param iterable|RememberMeHandlerInterface[] $rememberMeHandlers
32+
*/
33+
publicfunction__construct(iterable$rememberMeHandlers)
34+
{
35+
$this->rememberMeHandlers =$rememberMeHandlers;
36+
}
37+
38+
publicfunctionpostGenerateSchema(GenerateSchemaEventArgs$event):void
39+
{
40+
$dbalConnection =$event->getEntityManager()->getConnection();
41+
42+
foreach ($this->rememberMeHandlersas$rememberMeHandler) {
43+
if (
44+
$rememberMeHandlerinstanceof PersistentRememberMeHandler
45+
&& ($tokenProvider =$rememberMeHandler->getTokenProvider())instanceof DoctrineTokenProvider
46+
) {
47+
$tokenProvider->configureSchema($event->getSchema(),$dbalConnection);
48+
}
49+
}
50+
}
51+
52+
publicfunctiongetSubscribedEvents():array
53+
{
54+
if (!class_exists(ToolEvents::class)) {
55+
return [];
56+
}
57+
58+
return [
59+
ToolEvents::postGenerateSchema,
60+
];
61+
}
62+
}

‎src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
useDoctrine\DBAL\Connection;
1515
useDoctrine\DBAL\Driver\ResultasDriverResult;
1616
useDoctrine\DBAL\Result;
17+
useDoctrine\DBAL\Schema\Schema;
1718
useDoctrine\DBAL\Types\Types;
1819
useSymfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
1920
useSymfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface;
2021
useSymfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface;
2122
useSymfony\Component\Security\Core\Exception\TokenNotFoundException;
2223

2324
/**
24-
* This class provides storage for the tokens that is set in "rememberme"
25+
* This class provides storage for the tokens that is set in "remember-me"
2526
* cookies. This way no password secrets will be stored in the cookies on
2627
* the client machine, and thus the security is improved.
2728
*
@@ -53,8 +54,7 @@ public function __construct(Connection $conn)
5354
publicfunctionloadTokenBySeries(string$series)
5455
{
5556
// the alias for lastUsed works around case insensitivity in PostgreSQL
56-
$sql ='SELECT class, username, value, lastUsed AS last_used'
57-
.' FROM rememberme_token WHERE series=:series';
57+
$sql ='SELECT class, username, value, lastUsed AS last_used FROM rememberme_token WHERE series=:series';
5858
$paramValues = ['series' =>$series];
5959
$paramTypes = ['series' => \PDO::PARAM_STR];
6060
$stmt =$this->conn->executeQuery($sql,$paramValues,$paramTypes);
@@ -87,8 +87,7 @@ public function deleteTokenBySeries(string $series)
8787
*/
8888
publicfunctionupdateToken(string$series,string$tokenValue,\DateTime$lastUsed)
8989
{
90-
$sql ='UPDATE rememberme_token SET value=:value, lastUsed=:lastUsed'
91-
.' WHERE series=:series';
90+
$sql ='UPDATE rememberme_token SET value=:value, lastUsed=:lastUsed WHERE series=:series';
9291
$paramValues = [
9392
'value' =>$tokenValue,
9493
'lastUsed' =>$lastUsed,
@@ -114,9 +113,7 @@ public function updateToken(string $series, string $tokenValue, \DateTime $lastU
114113
*/
115114
publicfunctioncreateNewToken(PersistentTokenInterface$token)
116115
{
117-
$sql ='INSERT INTO rememberme_token'
118-
.' (class, username, series, value, lastUsed)'
119-
.' VALUES (:class, :username, :series, :value, :lastUsed)';
116+
$sql ='INSERT INTO rememberme_token (class, username, series, value, lastUsed) VALUES (:class, :username, :series, :value, :lastUsed)';
120117
$paramValues = [
121118
'class' =>$token->getClass(),
122119
// @deprecated since 5.3, change to $token->getUserIdentifier() in 6.0
@@ -138,4 +135,32 @@ public function createNewToken(PersistentTokenInterface $token)
138135
$this->conn->executeUpdate($sql,$paramValues,$paramTypes);
139136
}
140137
}
138+
139+
/**
140+
* Adds the Table to the Schema if "remember me" uses this Connection.
141+
*/
142+
publicfunctionconfigureSchema(Schema$schema,Connection$forConnection):void
143+
{
144+
// only update the schema for this connection
145+
if ($forConnection !==$this->conn) {
146+
return;
147+
}
148+
149+
if ($schema->hasTable('rememberme_token')) {
150+
return;
151+
}
152+
153+
$this->addTableToSchema($schema);
154+
}
155+
156+
privatefunctionaddTableToSchema(Schema$schema):void
157+
{
158+
$table =$schema->createTable('rememberme_token');
159+
$table->addColumn('series', Types::STRING, ['length' =>88]);
160+
$table->addColumn('value', Types::STRING, ['length' =>88]);
161+
$table->addColumn('lastUsed', Types::DATETIME_MUTABLE);
162+
$table->addColumn('class', Types::STRING, ['length' =>100]);
163+
$table->addColumn('username', Types::STRING, ['length' =>200]);
164+
$table->setPrimaryKey(['series']);
165+
}
141166
}

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class UnusedTagsPass implements CompilerPassInterface
7777
'security.authenticator.login_linker',
7878
'security.expression_language_provider',
7979
'security.remember_me_aware',
80+
'security.remember_me_handler',
8081
'security.voter',
8182
'serializer.encoder',
8283
'serializer.normalizer',

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/RegisterGlobalSecurityEventListenersPass.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
useSymfony\Component\Security\Http\Event\LoginFailureEvent;
2222
useSymfony\Component\Security\Http\Event\LoginSuccessEvent;
2323
useSymfony\Component\Security\Http\Event\LogoutEvent;
24+
useSymfony\Component\Security\Http\Event\TokenDeauthenticatedEvent;
2425
useSymfony\Component\Security\Http\SecurityEvents;
2526

2627
/**
@@ -44,6 +45,7 @@ class RegisterGlobalSecurityEventListenersPass implements CompilerPassInterface
4445
AuthenticationTokenCreatedEvent::class,
4546
AuthenticationSuccessEvent::class,
4647
InteractiveLoginEvent::class,
48+
TokenDeauthenticatedEvent::class,
4749

4850
// When events are registered by their name
4951
AuthenticationEvents::AUTHENTICATION_SUCCESS,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Bundle\SecurityBundle\DependencyInjection\Compiler;
13+
14+
useSymfony\Bundle\SecurityBundle\RememberMe\DecoratedRememberMeHandler;
15+
useSymfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16+
useSymfony\Component\DependencyInjection\ContainerBuilder;
17+
18+
/**
19+
* Replaces the DecoratedRememberMeHandler services with the real definition.
20+
*
21+
* @author Wouter de Jong <wouter@wouterj.nl>
22+
*
23+
* @internal
24+
*/
25+
finalclass ReplaceDecoratedRememberMeHandlerPassimplements CompilerPassInterface
26+
{
27+
privateconstHANDLER_TAG ='security.remember_me_handler';
28+
29+
/**
30+
* {@inheritdoc}
31+
*/
32+
publicfunctionprocess(ContainerBuilder$container):void
33+
{
34+
$handledFirewalls = [];
35+
foreach ($container->findTaggedServiceIds(self::HANDLER_TAG)as$definitionId =>$rememberMeHandlerTags) {
36+
$definition =$container->findDefinition($definitionId);
37+
if (DecoratedRememberMeHandler::class !==$definition->getClass()) {
38+
continue;
39+
}
40+
41+
// get the actual custom remember me handler definition (passed to the decorator)
42+
$realRememberMeHandler =$container->findDefinition((string)$definition->getArgument(0));
43+
if (null ===$realRememberMeHandler) {
44+
thrownew \LogicException(sprintf('Invalid service definition for custom remember me handler; no service found with ID "%s".', (string)$definition->getArgument(0)));
45+
}
46+
47+
foreach ($rememberMeHandlerTagsas$rememberMeHandlerTag) {
48+
// some custom handlers may be used on multiple firewalls in the same application
49+
if (\in_array($rememberMeHandlerTag['firewall'],$handledFirewalls,true)) {
50+
continue;
51+
}
52+
53+
$rememberMeHandler =clone$realRememberMeHandler;
54+
$rememberMeHandler->addTag(self::HANDLER_TAG,$rememberMeHandlerTag);
55+
$container->setDefinition('security.authenticator.remember_me_handler.'.$rememberMeHandlerTag['firewall'],$rememberMeHandler);
56+
57+
$handledFirewalls[] =$rememberMeHandlerTag['firewall'];
58+
}
59+
}
60+
}
61+
}

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/LoginLinkFactory.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,18 +113,24 @@ public function createAuthenticator(ContainerBuilder $container, string $firewal
113113
->replaceArgument(1,$config['lifetime']);
114114
}
115115

116+
$signatureHasherId ='security.authenticator.login_link_signature_hasher.'.$firewallName;
117+
$container
118+
->setDefinition($signatureHasherId,newChildDefinition('security.authenticator.abstract_login_link_signature_hasher'))
119+
->replaceArgument(1,$config['signature_properties'])
120+
->replaceArgument(3,$expiredStorageId ?newReference($expiredStorageId) :null)
121+
->replaceArgument(4,$config['max_uses'] ??null)
122+
;
123+
116124
$linkerId ='security.authenticator.login_link_handler.'.$firewallName;
117125
$linkerOptions = [
118126
'route_name' =>$config['check_route'],
119127
'lifetime' =>$config['lifetime'],
120-
'max_uses' =>$config['max_uses'] ??null,
121128
];
122129
$container
123130
->setDefinition($linkerId,newChildDefinition('security.authenticator.abstract_login_link_handler'))
124131
->replaceArgument(1,newReference($userProviderId))
125-
->replaceArgument(3,$config['signature_properties'])
126-
->replaceArgument(5,$linkerOptions)
127-
->replaceArgument(6,$expiredStorageId ?newReference($expiredStorageId) :null)
132+
->replaceArgument(2,newReference($signatureHasherId))
133+
->replaceArgument(3,$linkerOptions)
128134
->addTag('security.authenticator.login_linker', ['firewall' =>$firewallName])
129135
;
130136

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp