-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[9.x] Bind the encryption key object into the container #38793
Conversation
55fd8b2
to
3f363c4
Compare
I still think this is a bit overkill and unnecessary to introduce these breaking changes. I personally think it'd be easier to convert the |
Doing that change in just the https://github.com/laravel/passport/search?q=getKey The Passport example shows that |
2b6a88b
to
084dd6d
Compare
- avoid calling getKey method on the encrypter as it is not part of the contract
084dd6d
to
c8d5a90
Compare
Couldn't we introduce the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be the __toString()
approach…
@@ -39,15 +39,15 @@ class Encrypter implements EncrypterContract, StringEncrypter | |||
/** | |||
* Create a new encrypter instance. | |||
* | |||
* @param string $key | |||
* @param \Illuminate\Encryption\Key $key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @param \Illuminate\Encryption\Key $key | |
* @param \Illuminate\Encryption\Key|string $key |
* @param string $cipher | ||
* @return void | ||
* | ||
* @throws \RuntimeException | ||
*/ | ||
public function __construct($key, $cipher = 'aes-128-cbc') | ||
public function __construct(Key $key, string $cipher = 'aes-128-cbc') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function __construct(Key $key, string $cipher = 'aes-128-cbc') | |
public function __construct($key, string $cipher = 'aes-128-cbc') |
|
||
/** | ||
* Get the encryption key. | ||
* | ||
* @return string | ||
*/ | ||
public function getKey() | ||
{ | ||
return $this->key; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could leave getKey()
for backwards-compatibility reasons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The whole point of this PR is that this violates the contact so that's why it was removed. It's better to have it removed so that the callers have to fix their contract violations than leaving it in there and by doing so leaving a chance that the packages out there still violate the contract which makes this entire PR useless then.
* | ||
* @return string | ||
*/ | ||
public function getValue(): string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function getValue(): string | |
public function __toString(): string |
@@ -103,7 +113,7 @@ protected function validateValue(string $key, $value) | |||
{ | |||
return is_array($value) | |||
? $this->validateArray($key, $value) | |||
: CookieValuePrefix::validate($key, $value, $this->encrypter->getKey()); | |||
: CookieValuePrefix::validate($key, $value, $this->key->getValue()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
: CookieValuePrefix::validate($key, $value, $this->key->getValue()); | |
: CookieValuePrefix::validate($key, $value, $this->key); |
@@ -603,7 +604,7 @@ protected function prepareCookiesForRequest() | |||
} | |||
|
|||
return collect($this->defaultCookies)->map(function ($value, $key) { | |||
return encrypt(CookieValuePrefix::create($key, app('encrypter')->getKey()).$value, false); | |||
return encrypt(CookieValuePrefix::create($key, app(Key::class)->getValue()).$value, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return encrypt(CookieValuePrefix::create($key, app(Key::class)->getValue()).$value, false); | |
return encrypt(CookieValuePrefix::create($key, app(Key::class)).$value, false); |
@@ -90,7 +94,7 @@ protected function getEncryptedCookieValue($key, $value) | |||
$encrypter = $this->container->make(EncrypterContract::class); | |||
|
|||
return $encrypter->encrypt( | |||
CookieValuePrefix::create($key, $encrypter->getKey()).$value, | |||
CookieValuePrefix::create($key, $this->container->make(Key::class)->getValue()).$value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CookieValuePrefix::create($key, $this->container->make(Key::class)->getValue()).$value, | |
CookieValuePrefix::create($key, $this->container->make(Key::class)).$value, |
@@ -4,38 +4,39 @@ | |||
|
|||
use Illuminate\Contracts\Encryption\DecryptException; | |||
use Illuminate\Encryption\Encrypter; | |||
use Illuminate\Encryption\Key; | |||
use PHPUnit\Framework\TestCase; | |||
use RuntimeException; | |||
|
|||
class EncrypterTest extends TestCase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the changes to this test could be reverted.
$container->singleton('encrypter', function () use ($encrypter) { | ||
return $encrypter; | ||
}); | ||
|
||
$cookieName = 'cookie-name'; | ||
$cookieValue = 'cookie-value'; | ||
$encryptedValue = $encrypter->encrypt(CookieValuePrefix::create($cookieName, $encrypter->getKey()).$cookieValue, false); | ||
$encryptedValue = $encrypter->encrypt(CookieValuePrefix::create($cookieName, $key->getValue()).$cookieValue, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$encryptedValue = $encrypter->encrypt(CookieValuePrefix::create($cookieName, $key->getValue()).$cookieValue, false); | |
$encryptedValue = $encrypter->encrypt(CookieValuePrefix::create($cookieName, $key).$cookieValue, false); |
$container->singleton('encrypter', function () use ($encrypter) { | ||
return $encrypter; | ||
}); | ||
|
||
$cookieName = 'cookie-name'; | ||
$cookieValue = 'cookie-value'; | ||
$encryptedValue = $encrypter->encrypt( | ||
CookieValuePrefix::create($cookieName, $encrypter->getKey()).$cookieValue, false | ||
CookieValuePrefix::create($cookieName, $key->getValue()).$cookieValue, false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CookieValuePrefix::create($cookieName, $key->getValue()).$cookieValue, false | |
CookieValuePrefix::create($cookieName, $key).$cookieValue, false |
I could do that, but since changing |
But letting the Encrypter continue to use a string value means that all the existing code that expects it to be a string wouldn't be affected. The |
Honestly think the simplest thing is just adding |
IMO the encrypter contract should be about encrypting data, not about fetching the key. From what I see, @driesvints agrees with that too -> #38772 (comment) And from the user perspective it's a bit weird to need to get the encrypter just to get the key. Since both approaches have a similar BC impact we may as well go with the current approach, but that's just my 2 cents. |
But, here's the thing. 99.9% of Laravel users will never implement the encrypter contract or ever care at all that it has a |
I think we are approaching the same problem in different ways. I'm thinking from a software design perspective (how would I like the encrypter contract to look like), while you have a pragmatic maintainer/user view of the problem which takes into consideration the encrypter contract as it exists currently. Both POVs are perfectly valid. The entire diff consist of 100 added and 50 deleted lines of code and a lot of it are test changes which were done in a find & replace fashion (and which can be reverted by applying @inxilpro suggestion) so I think the diff in general is quite small. However if you wish so I can revert everything and just add that method to the contract. |
Yeah, honestly I think we should just add the I'll send up a commit for the contract. |
The
\Illuminate\Cookie\Middleware\EncryptCookies
middleware calls thegetKey
method which is not on the encrypter contract. This leads to broken applications when the users of the framework create their own encrypter implementation.This PR fixes this issue by making the key a value object that is bound into the container. By doing so anybody can typehint the
Key
class in their constructors and get the key that way now so there's no need to break the encrypter encapsulation with thegetKey
method.A side bonus of doing this is that people no longer need to copy paste the logic from
\Illuminate\Encryption\EncryptionServiceProvider::parseKey
every time when they need to construct just the key.There are only three very minor breaking changes here that won't affect 99% of the applications out there:
Key
instance instead of a stringgetKey
method on the encrypter has been removed. If the user needs the key they can just typehint it directly in the constructor instead of typehinting the Encrypter just to get the key.\Illuminate\Cookie\Middleware\EncryptCookies
middleware constructor now gets theKey
instance as the second parameter so if anyone overrode the constructor of that class in their app they will have to adjust it (but usually the only thing that changes in that class is the $except array).Fixes #38772