介绍

除了认证服务,laravel还提供了授权服务,laravel同样提供了一个简单的方式去组织授权的逻辑来控制资源的访问.我们提供了各种各样的方法协助你们组织授权的逻辑,这些都在下面的文档之中。

定义能力

如果用户想要执行某个动作并使用能力,最简单的方式是使用Illuminate\Auth\Access\Gate 类来定义。我们可以在AuthServiceProvider中定义应用程序中的所有能力。例如我们定义个update-post的能力,他将接受一个当前用户的Post模型,update-post能力将匹配用户的id和Post模型的user_id是否相等.

<?php

namespace App\Providers;

use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider
{
/**
* Register any application authentication / authorization services.
*
* @param \Illuminate\Contracts\Auth\Access\Gate $gate
* @return void
*/
public function boot(GateContract $gate)
{
$this->registerPolicies($gate); $gate->define('update-post', function ($user, $post) {
return $user->id === $post->user_id;
});
}
}

注意,我们并没用检测$user是否为null,因为如果当前用户没有认证或者指定了特殊的用户不做这个方法的验证,那么gate对象讲自动返回false.

基于类的能力

除了通过注册一个匿名函数,我们也可以注册类的方法,中间通过@符号链接,并且该类需要能够通过service container解析:

$gate->define('update-post', 'Class@method');

拦截授权检测

有的时候你需要对某些特殊的用户忽略所有能力。针对这种情况,可以使用before方法定义一个闭包,这个方法将在所有能力之前执行。

$gate->before(function ($user, $ability) {
if ($user->isSuperAdmin()) {
return true;
}
});

如果前置方法返回一个不为null的结果,那么这个结果将影响能力的检测.

你也可以定义后置方法,但是后置方法不会影响能力的检测结果:

$gate->after(function ($user, $ability, $result, $arguments) {
//
});

检测能力

当能力被定义了,我们可以使用多种方式去检测他,首先我们通过Gate facadecheck, allows和 denies方法来检测,所有这些方法都需要接受一个能力的名字和一个该能力对应回调函数的参数,你不需要传一个当前的用户到这些方法中,因为Gate会自动将当前认证用户传递到回调中。当然在我们使用update-post能力的时候我们需要提前定义,我只需要将Post的实例传递到denies方法中。

<?php

namespace App\Http\Controllers;

use Gate;
use App\User;
use App\Post;
use App\Http\Controllers\Controller; class PostController extends Controller
{
/**
* Update the given post.
*
* @param int $id
* @return Response
*/
public function update($id)
{
$post = Post::findOrFail($id); if (Gate::denies('update-post', $post)) {
abort(403);
} // Update Post...
}
}

这里也可以使用allows方法,该方法是denies的逆方法,当返回true的时候,则表示已授权.check方法是allows的别名方法。

针对某个特殊的用户授权检测

你可能需要通过Gate facade检测当前认证用户以外的用户,你可以使用forUser方法:

if (Gate::forUser($user)->allows('update-post', $post)) {
//
}

传递多个参数

当然,我们也可以给能力定义多个参数

Gate::define('delete-comment', function ($user, $post, $comment) {
//
});

如果能力定义了多个参数,我们需要以数组的形式将参数传递给Gate的方法:

if (Gate::allows('delete-comment', [$post, $comment])) {
//
}

通过User模型检测能力

另外,你也可以同过User模型的实例来检测能力,默认laravel的App\User模型使用了一个Authorizable trait,它将提供两个方法:cancannot。这些方法的使用和Gate facade的allows,denies一样,那么使用之前的例子,我们这个将代码修改为这样:

<?php

namespace App\Http\Controllers;

use App\Post;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller; class PostController extends Controller
{
/**
* Update the given post.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return Response
*/
public function update(Request $request, $id)
{
$post = Post::findOrFail($id); if ($request->user()->cannot('update-post', $post)) {
abort(403);
} // Update Post...
}
}

当然,can方法只是cannot的逆方法:

if ($request->user()->can('update-post', $post)) {
// Update Post...
}

在模板中使用

为了方便,laravel提供了一个@can指令去检车当前用户是否用于某个能力的授权,例如:

<a href="/post/{{ $post->id }}">View Post</a>

@can('update-post', $post)
<a href="/post/{{ $post->id }}/edit">Edit Post</a>
@endcan

你也可以结合@can指令使用@else指令:

@can('update-post', $post)
<!-- The Current User Can Update The Post -->
@else
<!-- The Current User Can't Update The Post -->
@endcan

在表单请求中使用

你也可以选择利用表单请求的authorize方法来检测授权:

/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$postId = $this->route('post'); return Gate::allows('update', Post::findOrFail($postId));
}

Policies

创建Policies

对于大型的应用,将所有自定义的授权逻辑全部放入AuthServiceProvider中,将会是一种累赘。laravel允许你讲授权逻辑拆分到多个Policy类中。Policies是一组是基于资源授权的授权逻辑的php类。

首先让我们生成一个policy来管理我们的post模型,生成一个policy,可以使用make:policy命令,他将生成一个空的app/Policies文件夹:

php artisan make:policy PostPolicy

注册Policies

当policy已存在,我们需要使用Gate类来注册他。并且AuthServiceProvider的policies属性必须包含这些policy类,同时我们也需要指定post模型的policy是PostPolicy类:

<?php

namespace App\Providers;

use App\Post;
use App\Policies\PostPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
Post::class => PostPolicy::class,
]; /**
* Register any application authentication / authorization services.
*
* @param \Illuminate\Contracts\Auth\Access\Gate $gate
* @return void
*/
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
}
}

编写Policies

当policy已经生成并注册,我们可以为没一个授权的能力添加方法。例如,我们添加一个update方法到我们的PostPolicy类中,它将定义用户时候可以更新post的数据:

?php

namespace App\Policies;

use App\User;
use App\Post; class PostPolicy
{
/**
* Determine if the given post can be updated by the user.
*
* @param \App\User $user
* @param \App\Post $post
* @return bool
*/
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
}

你也可以定义更多的方法到里面。例如,你可以需要定义:show, destroyaddComment等方法,去检测Post各个动作的授权。

注意,所有的policy都可以通过laravel的服务容器解析,这意味着我们可以通过类型提示将policy自动注入.

拦截所有的检测

有的时候,你希望在一个policy中一个特殊的用户忽略所有的ability,针对这种情况,我们可以在policy中定义before方法。这个方法将在这个policy中的所有ability之前执行:

public function before($user, $ability)
{
if ($user->isSuperAdmin()) {
return true;
}
}

检测Policies

policy方法的调用和基于授权的闭包函数一样。你也可以使用Gate facade,User模型,在模板中使用@can指令,或则使用policy辅助方法。

通过Gate facade

通过检测他们方法的参数,Gate可以自动确认需要使用哪个policy.比如,我们传递一个Post的实例到denies方法,他将自动使用PostPolicy类中对应的授权行为:

<?php

namespace App\Http\Controllers;

use Gate;
use App\User;
use App\Post;
use App\Http\Controllers\Controller; class PostController extends Controller
{
/**
* Update the given post.
*
* @param int $id
* @return Response
*/
public function update($id)
{
$post = Post::findOrFail($id); if (Gate::denies('update', $post)) {
abort(403);
} // Update Post...
}
}

通过User模型

User模型的can和cannot也会自动的利用policy

if ($user->can('update', $post)) {
//
} if ($user->cannot('update', $post)) {
//
}

在模板中使用

@can('update', $post)
<!-- The Current User Can Update The Post -->
@endcan

通过policy辅助方法

policy方法通过传入的对象的实例来检索需要使用哪个policy.例如,我们传入一个Post的实例到policy中,他将自动返回一个PostPolicy的实例:

if (policy($post)->update($user, $post)) {
//
}

控制器授权

默认App\Http\Controllers\Controller基类包含了一个AuthorizesRequests trait,这个trait将提供一个authorize方法,它可以使我们更快捷的对一个行为进行授权,如果没有权限将抛出一个HttpException的异常。

authorize方法和其他授权方法,如Gate::allows和$user->can()的参数一样,那么我么就可以这样来快速授权一个更新Post的请求:

<?php

namespace App\Http\Controllers;

use App\Post;
use App\Http\Controllers\Controller; class PostController extends Controller
{
/**
* Update the given post.
*
* @param int $id
* @return Response
*/
public function update($id)
{
$post = Post::findOrFail($id); $this->authorize('update', $post); // Update Post...
}
}

如果授权通过,那么这个控制前将继续执行,否则将抛出一个HttpException的异常,这个异常生成一个403的相应返回客户端

AuthorizesRequests trait也提供一个authorizeForUser方法,这个方法可以选择特定的用户授权:

$this->authorizeForUser($user, 'update', $post);

自动确定policy的方法

通常policy的方法都是符合控制器的方法的。例如:update方法,policy和控制器的方法名都一样。

基于这个结果,laravel允许你简化传递给authorize方法的参数,并且ability的授权的方法将自动的确认,这是基于控制器和Policy的方法名相同实现的,例如:这里的authorize方法在控制器的update方法中,那么这里将自动的调用PostPolicyupdate方法:

/**
* Update the given post.
*
* @param int $id
* @return Response
*/
public function update($id)
{
$post = Post::findOrFail($id); $this->authorize($post); // Update Post...
}

授权(Authorization)的更多相关文章

  1. [转].net中的认证(authentication)与授权(authorization)

    本文转自:http://www.cnblogs.com/yjmyzz/archive/2010/08/29/1812038.html 注:这篇文章主要给新手看的,老手们可能会觉得没啥营养,就请绕过吧. ...

  2. .net中的认证(authentication)与授权(authorization)

    “认证”与“授权”是几乎所有系统中都会涉及的概念,通俗点讲: 1.认证(authentication) 就是 "判断用户有没有登录?",好比windows系统,没登录就无法使用(不 ...

  3. mongodb的认证(authentication)与授权(authorization)

    一小白瞎整mongodb,认证部分被折磨的惨不忍睹,看厮可怜,特查了一下文档,浅显地总结一下mongodb认证(authentication)与授权(authorization)的联系. 创建的所有用 ...

  4. 认证 (authentication) 和授权 (authorization) 的区别

    authorization 授权 authentication 身份认证 用户认证流程: 1.用户使用username和password登录 2.系统验证这个password对于该username是正 ...

  5. 理解ASP.NET Core - 授权(Authorization)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 之前,我们已经了解了ASP.NET Core中的身份认证,现在,我们来聊一下授权. 老规矩,示 ...

  6. PHP CURL 账号密码 添加授权Authorization头Header

    <?phpfunction http_request_xml($url,$data = null,$arr_header = null){ $curl = curl_init(); curl_s ...

  7. 【转】认证 (authentication) 和授权 (authorization) 的区别

    以前一直分不清 authentication 和 authorization,其实很简单,举个例子来说: 你要登机,你需要出示你的身份证和机票,身份证是为了证明你张三确实是你张三,这就是 authen ...

  8. Security » Authorization » 基于资源的授权

    Resource Based Authorization¶ 基于资源的授权 68 of 73 people found this helpful Often authorization depends ...

  9. 认证(Authentication)和授权(Authorization)总结

    身份认证是验证你的身份,一旦通过验证,即启用授权.你所拥有的身份可以进行哪些操作都是由授权规定.例如,任何银行客户都可以创建一个账户(如用户名),并使用该账户登录该银行的网上服务,但银行的授权政策必须 ...

随机推荐

  1. jQuery 参考手册 - 文档操作

    上传图片时页面崩溃..全部付之东流 addClass() after() append() appendTo() attr() before() clone() detach() empty() ha ...

  2. linux vi快捷键大全

    h或^h 向左移一个字符 j或^j或^n 向下移一行 k或^p 向上移一行 l或空格 向右移一个字符 G 移到文件的最后一行 nG 移到文件的第n行 w 移到下一个字的开头 W 移到下一个字的开头,忽 ...

  3. SRM 358(1-250,500pt)

    DIV1 250pt 题意:电视目前停留在第100台,有一个遥控器,可以向上或向下换台(需要按键一次),也可以按一些数字,然后直接跳到该台(需要按键次数等于数字数,不需要按确定键).但是,这个遥控一些 ...

  4. hadoop的安装

    1. 获取linux操作系统 可以申请云主机. 2. 安装JDK,配置环境变量 sudo apt-get install openjdk-7-jdk vim /etc/profile 在配置文件中配置 ...

  5. 【转】[精华] 跟我一起写 Makefile

    陈皓 概述  —— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,m ...

  6. String+,StringBuilder,String.format运行效率比较

    实现String字符串相加的方法有很多,常见的有直接相加,StringBuilder.append和String.format,这三者的运行效率是有差异的,String是final类型的,每次相加都会 ...

  7. 一个分门别列介绍JavaScript各种常用工具的脑图

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:一个分门别列介绍JavaScript各种常用工具的脑图.

  8. ListView 选择多项目返回的之前的那项

      当ListView多选时返回第一次选中的项索引 正确 定义一个变量 =-1 表示第一次没选任何一项   private int FirstSelectedIndex =-1;     更新Firs ...

  9. LabVIEW的错误簇以及错误处理函数

    我们可以在LabVIEW的Modern>>Array, Matrix & Cluster控件面板找到表示错误簇数据类型的错误输入(Error In)以及错误输出(Error Out ...

  10. java注释 命名 数据类型 基本类型转换 位运算符 逻辑运算符 三目运算符

    一.java注释 1.单行注释  //注释内容 2.多行注释 /*注释内容*/ 3.文档注释(可用javadoc工具生成api文档,不过我还没试过)/**文档注释*/,文档注释可以在使用的时候看见注释 ...