Laravel 多授权资源
Laravel multi auth and authorize resource
我遇到以下情况的问题,希望能在这里找到建议:
我已经安装了 Laravel 5.7 并且 运行 make:auth 用于身份验证脚手架。本机用户模型已被删除,我使用两个自定义模型 "Customer" 和 "Admin"(迁移已相应更改)。
管理模式:
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Traits\FormatUserdata;
class Admin extends Authenticatable
{
use Notifiable, FormatUserdata;
protected $guard = 'admin';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'firstname', 'lastname', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
客户型号:
namespace App;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Traits\FormatUserdata;
class Customer extends Authenticatable
{
use HasApiTokens, Notifiable, FormatUserdata;
protected $guard = 'customer';
protected $fillable = [
'firstname', 'lastname', 'email', 'company', 'address', 'zip', 'city', 'country', 'vatid', 'customer_no', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function licenses()
{
return $this->hasMany('App\License');
}
}
所以我必须对来自两个不同模型和表的用户进行身份验证。为了让它工作,我改变了我的 config/auth.php 像这样:
return [
'defaults' => [
'guard' => 'customer',
'passwords' => 'customers',
],
'guards' => [
'customer' => [
'driver' => 'session',
'provider' => 'customers',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'api' => [
'driver' => 'passport',
'provider' => 'admins',
],
],
'providers' => [
'customers' => [
'driver' => 'eloquent',
'model' => App\Customer::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
],
'passwords' => [
'customers' => [
'provider' => 'customers',
'table' => 'password_resets',
'expire' => 60,
],
'admins' => [
'provider' => 'admins',
'table' => 'password_resets',
'expire' => 60,
],
],
];
对于我的客户模型,我设置了一个受资源策略保护的资源控制器以及索引方法的 auth 中间件:
namespace App\Http\Controllers;
use App\Customer;
use Illuminate\Http\Request;
class CustomerController extends Controller
{
public function __construct()
{
$this->middleware('auth:admin')->only('index');
$this->authorizeResource(Customer::class);
}
public function show(Customer $customer)
{}
...shortened
}
这是我在此控制器中引用的策略:
namespace App\Policies;
use App\Customer;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Foundation\Auth\User;
class CustomerPolicy
{
use HandlesAuthorization;
public function view(User $user, Customer $customer)
{
return true;
}
}
我的路由没有应用任何额外的中间件。
这里是问题所在:
当我使用默认守卫 "customer" 的用户访问我的路由 /customers/1 时,一切都按预期工作(没有错误)。但是,当我尝试使用管理员用户访问该路由时,我会收到 403 未经授权的响应。 st运行ge 的事情是,当我尝试使用
检查视图中的权限时
@can('view', App\Customer::findOrFail(3))
该政策工作正常。我发现当我以管理员身份访问路由时,根本没有调用策略的视图方法。我仔细研究了 laravel 代码,我很确定这个问题与以下事实有关:客户保护是默认的,而用户解析器只是默认的。
有人知道如何解决这个问题吗?
谢谢!
安德烈亚斯
编辑:
这是我的 AuthServiceProvicer.php:
namespace App\Providers;
use App\Policies\CustomerPolicy;
use App\Customer;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Customer::class => CustomerPolicy::class
];
public function boot()
{
$this->registerPolicies();
}
}
这是我的 routes/web。php
Route::get('/', function () {
return view('welcome');
});
Auth::routes(['register' => false]);
Route::prefix('admin')->name('admin.')->group(function () {
Route::get('/', function () {
return redirect( route('admin.dashboard') );
});
Route::get('dashboard', 'AdminController@dashboard')->name('dashboard');
Route::get('login', 'Auth\AdminLoginController@showLoginForm')->name('login');
Route::post('login', 'Auth\AdminLoginController@login')->name('login.post');
Route::post('logout', 'Auth\AdminLoginController@logout')->name('logout');
Route::post('password/email', 'Auth\AdminForgotPasswordController@sendResetLinkEmail')->name('password.email');
Route::get('password/reset', 'Auth\AdminForgotPasswordController@showLinkRequestForm')->name('password.request');
Route::post('password/reset', 'Auth\AdminResetPasswordController@reset')->name('password.update');
Route::post('password/reset/{token}', 'Auth\AdminResetPasswordController@showResetForm')->name('password.reset');
Route::resource('customers', 'CustomerController');
});
Route::prefix('backend')->name('backend.')->group(function () {
Route::get('/', function () {
return redirect( route('backend.dashboard') );
});
Route::get('dashboard', 'BackendController@dashboard')->name('dashboard');
Route::resource('customers', 'CustomerController')->except([
'index'
]);
});
因此,对于客户,我使用路由 /backend/customer/{customer},对于管理员,我使用路由 /admin/customer/{customer}
经过进一步研究,我发现了这个很棒的博客 post
https://medium.com/@JinoAntony/multi-user-authentication-using-guards-in-laravel-5-6-f18b4e61bdde
这里重要的一步是创建一个额外的中间件"AssignGuard",它根据使用的路由设置守卫。
我遇到以下情况的问题,希望能在这里找到建议:
我已经安装了 Laravel 5.7 并且 运行 make:auth 用于身份验证脚手架。本机用户模型已被删除,我使用两个自定义模型 "Customer" 和 "Admin"(迁移已相应更改)。
管理模式:
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Traits\FormatUserdata;
class Admin extends Authenticatable
{
use Notifiable, FormatUserdata;
protected $guard = 'admin';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'firstname', 'lastname', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
客户型号:
namespace App;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Traits\FormatUserdata;
class Customer extends Authenticatable
{
use HasApiTokens, Notifiable, FormatUserdata;
protected $guard = 'customer';
protected $fillable = [
'firstname', 'lastname', 'email', 'company', 'address', 'zip', 'city', 'country', 'vatid', 'customer_no', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function licenses()
{
return $this->hasMany('App\License');
}
}
所以我必须对来自两个不同模型和表的用户进行身份验证。为了让它工作,我改变了我的 config/auth.php 像这样:
return [
'defaults' => [
'guard' => 'customer',
'passwords' => 'customers',
],
'guards' => [
'customer' => [
'driver' => 'session',
'provider' => 'customers',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'api' => [
'driver' => 'passport',
'provider' => 'admins',
],
],
'providers' => [
'customers' => [
'driver' => 'eloquent',
'model' => App\Customer::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
],
'passwords' => [
'customers' => [
'provider' => 'customers',
'table' => 'password_resets',
'expire' => 60,
],
'admins' => [
'provider' => 'admins',
'table' => 'password_resets',
'expire' => 60,
],
],
];
对于我的客户模型,我设置了一个受资源策略保护的资源控制器以及索引方法的 auth 中间件:
namespace App\Http\Controllers;
use App\Customer;
use Illuminate\Http\Request;
class CustomerController extends Controller
{
public function __construct()
{
$this->middleware('auth:admin')->only('index');
$this->authorizeResource(Customer::class);
}
public function show(Customer $customer)
{}
...shortened
}
这是我在此控制器中引用的策略:
namespace App\Policies;
use App\Customer;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Foundation\Auth\User;
class CustomerPolicy
{
use HandlesAuthorization;
public function view(User $user, Customer $customer)
{
return true;
}
}
我的路由没有应用任何额外的中间件。
这里是问题所在:
当我使用默认守卫 "customer" 的用户访问我的路由 /customers/1 时,一切都按预期工作(没有错误)。但是,当我尝试使用管理员用户访问该路由时,我会收到 403 未经授权的响应。 st运行ge 的事情是,当我尝试使用
检查视图中的权限时@can('view', App\Customer::findOrFail(3))
该政策工作正常。我发现当我以管理员身份访问路由时,根本没有调用策略的视图方法。我仔细研究了 laravel 代码,我很确定这个问题与以下事实有关:客户保护是默认的,而用户解析器只是默认的。
有人知道如何解决这个问题吗?
谢谢! 安德烈亚斯
编辑:
这是我的 AuthServiceProvicer.php:
namespace App\Providers;
use App\Policies\CustomerPolicy;
use App\Customer;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Customer::class => CustomerPolicy::class
];
public function boot()
{
$this->registerPolicies();
}
}
这是我的 routes/web。php
Route::get('/', function () {
return view('welcome');
});
Auth::routes(['register' => false]);
Route::prefix('admin')->name('admin.')->group(function () {
Route::get('/', function () {
return redirect( route('admin.dashboard') );
});
Route::get('dashboard', 'AdminController@dashboard')->name('dashboard');
Route::get('login', 'Auth\AdminLoginController@showLoginForm')->name('login');
Route::post('login', 'Auth\AdminLoginController@login')->name('login.post');
Route::post('logout', 'Auth\AdminLoginController@logout')->name('logout');
Route::post('password/email', 'Auth\AdminForgotPasswordController@sendResetLinkEmail')->name('password.email');
Route::get('password/reset', 'Auth\AdminForgotPasswordController@showLinkRequestForm')->name('password.request');
Route::post('password/reset', 'Auth\AdminResetPasswordController@reset')->name('password.update');
Route::post('password/reset/{token}', 'Auth\AdminResetPasswordController@showResetForm')->name('password.reset');
Route::resource('customers', 'CustomerController');
});
Route::prefix('backend')->name('backend.')->group(function () {
Route::get('/', function () {
return redirect( route('backend.dashboard') );
});
Route::get('dashboard', 'BackendController@dashboard')->name('dashboard');
Route::resource('customers', 'CustomerController')->except([
'index'
]);
});
因此,对于客户,我使用路由 /backend/customer/{customer},对于管理员,我使用路由 /admin/customer/{customer}
经过进一步研究,我发现了这个很棒的博客 post
https://medium.com/@JinoAntony/multi-user-authentication-using-guards-in-laravel-5-6-f18b4e61bdde
这里重要的一步是创建一个额外的中间件"AssignGuard",它根据使用的路由设置守卫。