Laravel认证授权自定义:从members表认证、services表授权
嘿,我刚好折腾过类似的需求,给你一步步拆解怎么实现 Laravel 下用自定义表做认证和授权:
一、先搞定基于 members 表的用户认证
Laravel 的认证系统是可扩展的,我们只需要自定义认证模型和配置就能绕开默认的 users 表。
1. 创建 Member 模型
这个模型要实现 Laravel 认证所需的接口,指定对应的表和字段:
namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; class Member extends Authenticatable { // 指定使用 members 表 protected $table = 'members'; // 如果你的主键不是默认的 id,而是 Username,就加上这行 protected $primaryKey = 'Username'; // 允许批量赋值的字段,根据你的表结构调整 protected $fillable = ['Username', 'Rank', 'Name', 'Password']; // 重写密码字段获取方法,因为你的密码字段是 Password(首字母大写) public function getAuthPassword() { return $this->Password; } // 如果主键是 Username,还需要重写这两个方法 public function getAuthIdentifierName() { return 'Username'; } public function getAuthIdentifier() { return $this->getKey(); } }
2. 修改认证配置文件
打开 config/auth.php,调整 guard 和 provider 配置,让系统使用我们的 Member 模型:
return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'members', // 这里也改成 members ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'members', // 把 provider 换成 members ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], // 添加我们的 members 提供者 'members' => [ 'driver' => 'eloquent', 'model' => App\Models\Member::class, ], ], // 别忘了添加密码重置的配置(如果需要的话) 'passwords' => [ 'members' => [ 'provider' => 'members', 'table' => 'password_resets', 'expire' => 60, 'throttle' => 60, ], ], ];
3. 自定义登录控制器(可选,也可以改默认的)
如果你不想用默认的 LoginController,就新建一个专门的 MemberLoginController,指定使用我们的 guard:
namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Support\Facades\Auth; class MemberLoginController extends Controller { use AuthenticatesUsers; // 登录成功后的跳转路径 protected $redirectTo = '/dashboard'; public function __construct() { $this->middleware('guest')->except('logout'); } // 指定使用 members guard 进行认证 protected function guard() { return Auth::guard('members'); } // 重写登录字段,因为我们用的是 Username 而不是默认的 email public function username() { return 'Username'; } }
然后在 routes/web.php 里添加登录路由:
Route::get('/member/login', [App\Http\Controllers\Auth\MemberLoginController::class, 'showLoginForm'])->name('member.login'); Route::post('/member/login', [App\Http\Controllers\Auth\MemberLoginController::class, 'login']); Route::post('/member/logout', [App\Http\Controllers\Auth\MemberLoginController::class, 'logout'])->name('member.logout');
二、基于 services 表的权限授权
接下来处理权限部分,我们可以用 Laravel 的 Gate 或者 Policy 来实现,结合 services 表的数据。
1. 创建 Service 模型并关联 Member
先定义 Service 模型,建立和 Member 的关联:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Service extends Model { protected $table = 'services'; protected $fillable = ['username', 'user_services']; // 关联 Member 模型,外键是 username 对应 members 表的 Username public function member() { return $this->belongsTo(Member::class, 'username', 'Username'); } }
然后在 Member 模型里添加反向关联:
// 在 App\Models\Member 里添加 public function services() { return $this->hasMany(Service::class, 'username', 'Username'); }
2. 用 Gate 定义权限规则
打开 app/Providers/AuthServiceProvider.php,在 boot 方法里定义权限检查逻辑:
use App\Models\Member; use Illuminate\Support\Facades\Gate; public function boot() { $this->registerPolicies(); // 定义一个通用的权限检查 Gate:检查用户是否有权限访问某个服务 Gate::define('access-service', function (Member $member, $serviceName) { // 从 services 表查询该用户是否拥有指定服务 return $member->services()->where('user_services', $serviceName)->exists(); }); }
3. 在代码中使用权限检查
控制器里检查:
public function payment() { // 检查当前登录用户是否有权限访问 payment 服务 if (!Gate::allows('access-service', 'payment')) { abort(403, '你没有权限访问该服务'); } return view('payment.index'); }
视图里检查:
@can('access-service', 'payment') <a href="/payment" class="btn btn-primary">支付服务</a> @else <span class="text-muted">无支付权限</span> @endcan
4. (可选)自定义权限中间件
如果要在路由层面统一检查权限,可以创建一个中间件:
namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Gate; class CheckServiceAccess { public function handle($request, Closure $next, $service) { if (!Gate::allows('access-service', $service)) { abort(403, '无权限访问该服务'); } return $next($request); } }
然后在 app/Http/Kernel.php 里注册这个中间件:
protected $routeMiddleware = [ // ...其他中间件 'service.access' => \App\Http\Middleware\CheckServiceAccess::class, ];
之后就可以在路由里直接使用:
Route::get('/payment', [PaymentController::class, 'index'])->middleware('service.access:payment');
注意事项
- 确保 members 表的 Password 字段存储的是哈希后的密码,注册用户时要用
Hash::make($password)来加密。 - 如果你的 members 表主键不是自增 ID(比如 Username 是字符串),要在 Member 模型里加上
public $incrementing = false;和protected $keyType = 'string';。 - 测试时要清空浏览器缓存,避免之前的 session 干扰。
如果某个步骤出现报错,比如认证失败、权限检查不生效,可以贴出具体的错误信息,我再帮你排查~
内容的提问来源于stack exchange,提问作者Hemant Maurya
相关产品推荐
相关产品推荐

