我在Laravel中实现了如下用户策略。
namespace App\Policies;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class UserPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can list the model.
*
* @param \App\User $user
* @return mixed
*/
public function index(User $user)
{
// only a chief editor can view all users
$authorized = false;
$authorized = ($user->role->name === 'Chief Editor');
return $authorized;
}
/**
* Determine whether the user can view the model.
*
* @param \App\User $user
* @param \App\User $model
* @return mixed
*/
public function view(User $user, User $model)
{
// only a chief editor or user(who owns the user) can view the user
$authorized = false;
$authorized = ($user->role->name === 'Chief Editor' || $user->id === $model->id);
return $authorized;
}
/**
* Determine whether the user can create models.
*
* @param \App\User $user
* @return mixed
*/
public function create(User $user)
{
// only a chief editor can create a user
$authorized = false;
$authorized = ($user->role->name === 'Chief Editor');
return $authorized;
}
/**
* Determine whether the user can update the model.
*
* @param \App\User $user
* @param \App\User $model
* @return mixed
*/
public function update(User $user, User $model)
{
// only a chief editor or user(who owns the user) can update the user
$authorized = false;
$authorized = ($user->role->name === 'Chief Editor' || $user->id === $model->id);
return $authorized;
}
/**
* Determine whether the user can delete the model.
*
* @param \App\User $user
* @param \App\User $model
* @return mixed
*/
public function delete(User $user, User $model)
{
// only a chief editor or user(who owns the user) can delete the user
$authorized = false;
$authorized = ($user->role->name === 'Chief Editor' || $user->id === $model->id);
return $authorized;
}
}
这是我的用户控制器。
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\StoreUser;
use App\Http\Requests\UpdateUser;
use App\User;
use App\Role;
class UserController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->middleware('can:index,App\User')->only('index');
$this->middleware('can:view,user')->only('show');
$this->middleware('can:create,App\User')->only('create', 'store');
$this->middleware('can:update,user')->only('edit', 'update');
$this->middleware('can:delete,user')->only('destroy');
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$users = User::paginate(5);
return view('users.index')
->with('users', $users);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
// fetch roles
$roles = Role::all();
return view('users.create')
->with('roles', $roles);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(StoreUser $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$user = User::findOrFail($id);
return view('users.show')
->with('user', $user);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
$user = User::findOrFail($id);
return view('users.edit')
->with('user', $user);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(UpdateUser $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
但是,当我在策略方法中访问具有多个参数的操作(两个用户对象)时,我收到This action is unauthorized.
错误。
我还尝试在不使用这些方法的任何检查的情况下返回true
但仍然存在同样的问题。
这是我的代码问题还是Laravel的错误?
答案 0 :(得分:0)
更新:您的代码无效,因为您没有将第二个用户传递给该政策。
您没有使用路由模型绑定,因此传递给view
方法的用户不存在。当模型不存在时,Laravel将不会检查策略并返回false。
以下是文档中的示例,它的工作原理是路由模型绑定。
Route::put('/post/{post}', function (Post $post) {
// The current user may update the post...
})->middleware('can:update,post');
答案:
在控制器构造函数中使用授权是没有意义的。如果要使用中间件进行授权,请将其附加到不是控制器的路径上。
如果您允许请求到达控制器,那么最好检查操作中的授权而不是构造函数。它也更容易阅读和调试。
我会从构造函数中删除对can
中间件的所有调用,并将其替换为操作中对authorize
的调用。
你的控制器应该是这样的:
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$this-authorize('index'); // This will check for authorization
$users = User::paginate(5);
return view('users.index')
->with('users', $users);
}
public function show($id)
{
$user = User::findOrFail($id);
$this->authorize('view', $user);
return view('users.show')
->with('user', $user);
}
此外,您的策略类中不需要temprory变量。
public function index(User $user)
{
// only a chief editor can view all users
return $user->role->name === 'Chief Editor'
}
public function view(User $user, User $model)
{
// only a chief editor or user(who owns the user) can view the user
return $user->role->name === 'Chief Editor' || $user->id === $model->id)
}
作为旁注,在您的节目动作中,为什么不使用implicit route model binding?它会更清洁。
// web.php
Route::get('users/{user}', 'UserController@show');
// UserController.php
public function show(User $user)
{
$this->authorize('view', $user);
return view('users.show', compact('user');
}