Laravel中如何在同一浏览器管理管理员与用户并区分会话?
在Laravel同一浏览器中区分管理员与普通用户会话的方案
嘿,这个问题我之前帮好几个开发者解决过,Laravel里其实有挺直接的方案来区分管理员和普通用户的会话,甚至能在同一浏览器同时登录两种角色——下面给你拆解具体步骤:
核心思路:利用Laravel的「认证守卫(Guard)」
Laravel的Auth系统本身就支持多守卫,默认的web守卫对应普通用户,我们只需要新增一个admin守卫,让两个守卫使用独立的会话存储,就能实现区分。
1. 配置认证守卫与用户提供者
首先修改config/auth.php,新增admin守卫和对应的用户提供者:
// config/auth.php return [ // ...其他配置 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], // 新增管理员守卫 'admin' => [ 'driver' => 'session', 'provider' => 'admins', ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], // 新增管理员提供者,指向Admin模型 'admins' => [ 'driver' => 'eloquent', 'model' => App\Models\Admin::class, ], ], ];
2. 创建Admin模型与数据库迁移
如果还没有Admin模型,先创建一个(和User模型结构类似,可根据需求加权限字段):
// app/Models/Admin.php namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class Admin extends Authenticatable { use Notifiable; // 指定该模型使用admin守卫 protected $guard = 'admin'; protected $fillable = [ 'name', 'email', 'password', ]; protected $hidden = [ 'password', 'remember_token', ]; }
然后生成对应的数据库迁移,执行迁移创建admins表(字段和users表一致即可,或者按需扩展)。
3. 编写独立的管理员登录逻辑
创建专属的管理员登录控制器,指定使用admin守卫:
// app/Http/Controllers/Admin/Auth/LoginController.php namespace App\Http\Controllers\Admin\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; class LoginController extends Controller { use AuthenticatesUsers; // 管理员登录后的跳转地址 protected $redirectTo = '/admin/dashboard'; public function __construct() { // 未登录的管理员才能访问登录页 $this->middleware('guest:admin')->except('logout'); } // 指定使用admin守卫进行认证 protected function guard() { return auth()->guard('admin'); } // 加载管理员登录视图 public function showLoginForm() { return view('admin.auth.login'); } // 管理员登出逻辑 public function logout(Request $request) { $this->guard()->logout(); $request->session()->invalidate(); return redirect('/admin/login'); } }
普通用户的登录逻辑保持默认的web守卫即可。
4. 配置独立的路由组
给管理员配置单独的路由前缀和中间件,确保只有认证后的管理员能访问:
// routes/web.php // 普通用户路由(保持默认) Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home'); // 管理员路由组 Route::prefix('admin')->name('admin.')->group(function () { // 管理员登录相关路由 Route::get('/login', [App\Http\Controllers\Admin\Auth\LoginController::class, 'showLoginForm'])->name('login'); Route::post('/login', [App\Http\Controllers\Admin\Auth\LoginController::class, 'login'])->name('login.submit'); Route::post('/logout', [App\Http\Controllers\Admin\Auth\LoginController::class, 'logout'])->name('logout'); // 管理员后台路由(需要认证) Route::middleware('auth:admin')->group(function () { Route::get('/dashboard', [App\Http\Controllers\Admin\DashboardController::class, 'index'])->name('dashboard'); // 其他管理员专属路由... }); });
会话区分的原理
不同的守卫会在Session中存储独立的认证标识,比如:
- 普通用户(web守卫)的会话键为
login_web_xxxxxxxxxx - 管理员(admin守卫)的会话键为
login_admin_xxxxxxxxxx
这两个键会同时存在于浏览器的Session中,互相独立,不会覆盖对方的登录状态,所以你能在同一浏览器里同时登录两种角色。
视图中区分登录状态
在Blade模板里,可以分别检查不同守卫的登录状态:
{{-- 普通用户登录状态 --}} @auth('web') <div class="user-nav"> 欢迎,{{ auth()->user()->name }} | <a href="{{ route('logout') }}">退出登录</a> </div> @endauth {{-- 管理员登录状态 --}} @auth('admin') <div class="admin-nav"> 管理员:{{ auth()->guard('admin')->user()->name }} | <a href="{{ route('admin.logout') }}">退出</a> </div> @endauth {{-- 未登录状态 --}} @guest('web') <a href="{{ route('login') }}">用户登录</a> @endguest @guest('admin') <a href="{{ route('admin.login') }}">管理员登录</a> @endguest
额外小贴士
- 如果不想单独创建Admin模型,也可以用单一User模型加
role字段,但这种方式无法实现同一浏览器同时登录,因为会话共用同一个守卫,只能切换角色登录。 - 确保Session配置正常(
config/session.php),比如驱动用file或database,不要用array(数组驱动只用于测试)。
这样设置之后,你就能完全区分管理员和普通用户的会话,甚至在同一浏览器里同时操作两种角色,亲测好用,很多生产项目都是这么实现的~
内容的提问来源于stack exchange,提问作者Jwala Singh
相关产品推荐
相关产品推荐

