Аннулирование сессий на других устройствах в Laravel
выходаиз сеансов активного пользователя на других устройствах без аннулирования сеанса на текущем устройстве.
Недавно у меня украли мобильный телефон, и я понял, как много приложений не имеют функции контроля сеанса. Я не мог выйти из системы с этого устройства.
К счастью, Laravel предоставляет способ аннулирования и выхода
из сеансов активного пользователя на других устройствах без аннулирования сеанса на его текущем устройстве.
Ниже я перечислю несколько случаев, когда эта функция может быть полезной:
- Пользователь потерял или у него украли устройство.
- Пользователь меняет свой пароль.
- Приложение не должно разрешать несколько сеансов одновременно.
Аннулирование сеансов на других устройствах
Чтобы аннулировать сессию пользователя на всех устройствах, кроме текущего, необходимо вызвать метод Auth::logoutOtherDevices
. Он требует от пользователя подтверждения пароля.
Это важно, поскольку если пользователь потерял или у него украли мобильный телефон, вы не можете позволить кому-то выйти из всех сессий, использующих это устройство.
use Illuminate\Support\Facades\Auth;
Auth::logoutOtherDevices($currentPassword);
Чтобы метод logoutOtherDevices
работал, Laravel предоставляет Illuminate\Session\Middleware\AuthenticateSession
middleware, которое обнаруживает изменение хэша пароля, немедленно выводит пользователя из системы и запускает событие Illuminate\Auth\Events\CurrentDeviceLogout
.
По умолчанию middleware
AuthenticateSession
может быть присоединено к маршруту с использованием псевдонима middleware маршрутаauth.session
, как определено в HTTP ядре приложения. Официальная документация Laravel
routes/web.php:
Route::middleware(['auth', 'auth.session'])->group(function () {
Route::get('/', function () {
// ...
});
});
Тогда вы, возможно, уже думаете, что делает logoutOtherDevices
. Это повторное хэширование пароля. Хм, но меняется ли хэш даже при использовании одного и того же пароля? Да, меняется!
Аннулирование сессии определённого устройства
Это возможно, но вы должны управлять сессиями с помощью драйвера базы данных. Это позволяет запрашивать сессии и отображать список, чтобы пользователь мог выбрать конкретную сессию для аннулирования.
Драйверу базы данных нужна таблица. Вы можете использовать команду artisan session:table
для создания такой миграции.
php artisan session:table
php artisan migrate
Установите драйвер в файле config/session.php
в качестве базы данных:
//...
'driver' => env('SESSION_DRIVER', 'database')
//...
Или через атрибут SESSION_DRIVER
в env-файле:
SESSION_DRIVER=database
Затем создайте модель для таблицы сессий:
php artisan make:model Session
Создайте отношения:
app/Models/Session.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Session extends Model
{
public $incrementing = false;
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
app/Models/User.php:
namespace App\Models;
//...
use Illuminate\Database\Eloquent\Relations\HasMany;
class User extends Authenticatable
{
//...
public function sessions(): HasMany
{
return $this->hasMany(Session::class);
}
}
Теперь вы можете составить список сеансов:
$user = auth()->user();
$sessions = $user->sessions()
->select('id', 'ip_address', 'user_agent', 'last_activity')
->get();
dump($sessions->toArray());
Пример того, как это должно выглядеть:
array:3 [▼ // routes/web.php:18
0 => array:4 [▶
"id" => "J9KBJgsqKWRu4JGhNpTF73EBhGXD9FneIR2vzEqX"
"ip_address" => "217.240.75.140"
"user_agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ..."
"last_activity" => 1688043153
]
1 => array:4 [▶
"id" => "mfmRbbeR803hPpi0uLlPYtWaahqgw6CglEu5UMv7"
"ip_address" => "21.51.178.175"
"user_agent" => "Mozilla/5.0 (iPhone; CPU iPhone OS 11_6_9; like Mac OS X) ..."
"last_activity" => 1688043136
]
2 => array:4 [▶
"id" => "VCkIFZN0zjKq808gvps7haz8XzOkOjnxVlZQifwe"
"ip_address" => "25.31.180.18"
"user_agent" => "Mozilla / 5.0 (compatible; MSIE 8.0; Windows; U; Windows NT 10.0; WOW64; en-US Trident / 4.0)"
"last_activity" => 1688043145
]
]
Наконец, чтобы уничтожить конкретную сессию, необходимо удалить её из базы данных. В приведённом ниже примере мы отсоединяем iPhone:
$user->sessions()
->where('id', 'mfmRbbeR803hPpi0uLlPYtWaahqgw6CglEu5UMv7')
->delete();
В заключение
В этой статье вы узнали о важности контроля сеансов на каждом устройстве и о том, как этого можно добиться с помощью Laravel.