开始
$this->authorize('edits',$user);
这个方法是调用了Illuminate\Foundation\Auth\Access\AuthorizesRequests
中的authorize
方法:
public function authorize($ability, $arguments = [])
{
list($ability, $arguments) = $this->parseAbilityAndArguments($ability, $arguments);
return app(Gate::class)->authorize($ability, $arguments);
}
接着是Gate::class
下的authorize
方法:
public function authorize($ability, $arguments = [])
{
$result = $this->raw($ability, $arguments);
if ($result instanceof Response) {
return $result;
}
return $result ? $this->allow() : $this->deny();
}
其中raw
方法为:
protected function raw($ability,$arguments=[]){
if(!$user=$this->resolveUser()){
return false;
}
$arguments=array_merge($argument);
$result=$this->callBeforeCallbacks($user,$ability,$arguments);
if(is_null($result)){
$result=$this->callAuthCallback($user,$ability,$arguments);
}
$this->callAfterCallbacks($user,$ability,$argument,$result);
return $result;
}
其中重点之一就是resolveUser()
这个函数,可是这个函数偏偏又是最模糊的存在:
protected function resolveUser(){
return call_user_func($this->userResolver);
}
接着问题就很奇怪了,这个参数是在Gate
类的构造函数中指定的,可是外界又是通过服务容器的全局函数app()
调用的该类,那么我怎么知道该userResolver
参数在哪里呢?于是我调用了PHPStorm
的全局内容搜索:Ctrl+Shift+F
,找到了其传入到服务容器中时设置的函数:
//该函数位于 Illuminate\Auth\AuthServiceProvider.php 中
protected function registerAccessGate()
{
$this->app->singleton(GateContract::class, function ($app) {
return new Gate($app, function () use ($app) {
return call_user_func($app['auth']->userResolver());
});
});
}
这里的GateContract::class
其实是在命名空间中使用了别名,原始名称是:Illuminate\Contracts\Auth\Access\Gate
,是不是!就问是不是我们的Gate
类!!!
所以下一个问题就是这个$app['auth']->userResolver()
是什么了,在\Illuminate\Foundation\Application.php
中,我们找到了答案:
'auth'=> [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class],
所以我们去看AuthManager
类中的userResolver
方法:
public function userResolver()
{
return $this->userResolver;
}
肯定是在构造函数中指定了该参数:
public function __construct($app)
{
$this->app = $app;
$this->userResolver = function ($guard = null) {
return $this->guard($guard)->user();
};
}
WTF,这是什么鬼!!!我只是想知道一个函数而已,要不要这么玩我啊!!!没办法,继续跟进,于是就去搜这个user()
是什么鬼:
public function user()
{
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}
return $this->user = call_user_func(
$this->callback, $this->request
);
}
这个类的使用情况有点超出授权的范畴了,之后再讨论,经过上面的过程,我们知道了一个情况,在最开始的$user=$this->resolveUser()
返回的$user
是经过Laravel
确认的当前身份用户
return is_callable([$policy, $ability])
? $policy->{$ability}($user, ...$arguments)
: false;
调用了Policies
文件下的
public function edits(User $currentUser,User $user){
return $currentUser->id===$user->id;
}
这样的形式,所以第一个$currentUser
是根据guard
的中间件来的,这部分后面再讨论,而后一个$user
则是我们在控制器中传入的参数。