PHP Native Session with Laravel
source link: https://blog.deleu.dev/php-native-session-with-laravel/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
PHP Native Session with Laravel
October 18, 2020
Completely replacing legacy code is hard. Rebuilding years of work doesn’t happen overnight. The strangler pattern offers a strategy to slowly and gradually replace a legacy codebase with a fresh one piece by piece. One of the key aspects of getting a successful project get started in replacing a legacy codebase was keeping the authentication system working. Let me set the scene.
Context
A 15-year old codebase written in PHP using $_SESSION
across
several thousands of files lives behind a web server running
under api.mydomain.com
. It acts as a backend api for a
frontend application that establish these API calls using
PHP browser’s cookie (PHPSESSID). We can start a brand new project
and call it api.v2.mydomain.com
or we can use path-based
routing and define an ALB routing on AWS where
api.mydomain.com/v2
automatically routes to this second project.
The new project can take advantage of modern php development
(a public framework, composer, tdd, etc), but developing
a brand new authentication system is a huge undertake at this
point. It requires changes to the authentication process,
the frontend and the backend project. A less disruptive
process would be to simply focus on making the v2 project
viable while keeping as much backward compatibility as possible.
Laravel Authentication with $_SESSION
Laravel PHP Session
is a package that helps achieve exactly that. We install it
via composer require customergauge/session
and configure
auth.php
with a new authentication mechanism.
'guards' => [
'php' => [
'driver' => \CustomerGauge\Session\NativeSessionGuard::class,
'provider' => \CustomerGauge\Session\NativeSessionUserProvider::class,
'domain' => '.mydomain.com',
'storage' => 'tcp://my-redis-address:6379',
],
],
The domain
attribute is directly mapped to PHP’s COOKIE_DOMAIN
ini setting and the storage
is mapped to SESSION_PATH
.
The next step is to implement the UserFactory
interface
and bind it into Laravel’s Container.
final class NativeSessionUserFactory implements UserFactory
{
public function make(array $session): ?Authenticatable
{
// $session here is the same as $_SESSION
if (empty($session['id'])) {
return null;
}
return new MyUser(
(int) $session['id'],
$session['my_session_attribute']
);
}
}
Laravel’s auth middleware allows us to specify a guard
when
declaring a route as authenticatable. See more on https://laravel.com/docs/8.x/authentication#protecting-routes.
As long as our route is protected by auth:php
, the authentication
process will be triggered.
Test Code
Laravel already provides the actingAs
functionality in
it’s TestCase classes. That functionality will allow us
to bind a specific user object into the container so that
the application treat the execution test as authenticated.
To avoid any problems with the PHP Native session, we can also
bind a mock instance of SessionRetriever into the container
protected function setUp(): void
{
parent::setUp();
$fakeSession = ['id' => 'my-fake-$_SESSION-content'];
$this->app->instance(SessionRetriever::class, SessionRetriever::fake($fakeSession));
}
This bind will prevent any execution path that might lead to
SessionRetriever calling sesion_start()
, which would fail
under phpunit as there’s no headers
to be sent.
Conclusion
I’ve been using this strategy for well over 3 years now and
it empowered my team to strangle more and more our legacy
codebase into a modern application in small, incremental
steps. The more code we move to services designed with this
mindset, the less $_SESSION
spread across a codebase we have
and the closer we get to having a consistent authentication
mechanism that might easily be replaced by another Laravel
Guard. As a matter of fact, we already have a Laravel Guard
for AWS Cognito that I wrote about here.
As always, hit me up on Twitter with any questions.
Cheers.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK