Skip to content

Commit 988de8a

Browse files
authored
[11.x] Cache token repository (#53428)
* wip * Update CacheTokenRepository.php - store the carbon date as a formatted string - use the existing `delete()` method - simplify constructor and properties * Update PasswordBrokerManager.php have the `PasswordBrokerManager` pass in expiration as seconds * styling * minor styling * check for set "driver" key
1 parent 71dfdc0 commit 988de8a

File tree

2 files changed

+135
-2
lines changed

2 files changed

+135
-2
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<?php
2+
3+
namespace Illuminate\Auth\Passwords;
4+
5+
use Illuminate\Cache\Repository;
6+
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
7+
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
8+
use Illuminate\Support\Carbon;
9+
use Illuminate\Support\Str;
10+
11+
class CacheTokenRepository implements TokenRepositoryInterface
12+
{
13+
/**
14+
* The format of the stored Carbon object.
15+
*/
16+
protected string $format = 'Y-m-d H:i:s';
17+
18+
/**
19+
* Create a new token repository instance.
20+
*/
21+
public function __construct(
22+
protected Repository $cache,
23+
protected HasherContract $hasher,
24+
protected string $hashKey,
25+
protected int $expires = 3600,
26+
protected int $throttle = 60
27+
) {
28+
}
29+
30+
/**
31+
* Create a new token.
32+
*
33+
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
34+
* @return string
35+
*/
36+
public function create(CanResetPasswordContract $user)
37+
{
38+
$email = $user->getEmailForPasswordReset();
39+
40+
$this->delete($user);
41+
42+
$token = hash_hmac('sha256', Str::random(40), $this->hashKey);
43+
44+
$this->cache->put($email, [$token, Carbon::now()->format($this->format)], $this->expires);
45+
46+
return $token;
47+
}
48+
49+
/**
50+
* Determine if a token record exists and is valid.
51+
*
52+
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
53+
* @param string $token
54+
* @return bool
55+
*/
56+
public function exists(CanResetPasswordContract $user, #[\SensitiveParameter] $token)
57+
{
58+
[$record, $createdAt] = $this->cache->get($user->getEmailForPasswordReset());
59+
60+
return $record
61+
&& ! $this->tokenExpired($createdAt)
62+
&& $this->hasher->check($token, $record);
63+
}
64+
65+
/**
66+
* Determine if the token has expired.
67+
*
68+
* @param string $createdAt
69+
* @return bool
70+
*/
71+
protected function tokenExpired($createdAt)
72+
{
73+
return Carbon::createFromFormat($this->format, $createdAt)->addSeconds($this->expires)->isPast();
74+
}
75+
76+
/**
77+
* Determine if the given user recently created a password reset token.
78+
*
79+
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
80+
* @return bool
81+
*/
82+
public function recentlyCreatedToken(CanResetPasswordContract $user)
83+
{
84+
[$record, $createdAt] = $this->cache->get($user->getEmailForPasswordReset());
85+
86+
return $record && $this->tokenRecentlyCreated($createdAt);
87+
}
88+
89+
/**
90+
* Determine if the token was recently created.
91+
*
92+
* @param string $createdAt
93+
* @return bool
94+
*/
95+
protected function tokenRecentlyCreated($createdAt)
96+
{
97+
if ($this->throttle <= 0) {
98+
return false;
99+
}
100+
101+
return Carbon::createFromFormat($this->format, $createdAt)->addSeconds(
102+
$this->throttle
103+
)->isFuture();
104+
}
105+
106+
/**
107+
* Delete a token record.
108+
*
109+
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
110+
* @return void
111+
*/
112+
public function delete(CanResetPasswordContract $user)
113+
{
114+
$this->cache->forget($user->getEmailForPasswordReset());
115+
}
116+
117+
/**
118+
* Delete expired tokens.
119+
*
120+
* @return void
121+
*/
122+
public function deleteExpired()
123+
{
124+
}
125+
}

src/Illuminate/Auth/Passwords/PasswordBrokerManager.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,18 @@ protected function createTokenRepository(array $config)
8888
$key = base64_decode(substr($key, 7));
8989
}
9090

91-
$connection = $config['connection'] ?? null;
91+
if (isset($config['driver']) && $config['driver'] === 'cache') {
92+
return new CacheTokenRepository(
93+
$this->app['cache']->store($config['store'] ?? null),
94+
$this->app['hash'],
95+
$key,
96+
($config['expire'] ?? 60) * 60,
97+
$config['throttle'] ?? 0
98+
);
99+
}
92100

93101
return new DatabaseTokenRepository(
94-
$this->app['db']->connection($connection),
102+
$this->app['db']->connection($config['connection'] ?? null),
95103
$this->app['hash'],
96104
$config['table'],
97105
$key,

0 commit comments

Comments
 (0)