这一节咱们将给相关的动做页面添加权限,如已经登陆的用户将不会看到注册、登陆按钮,更不会对别人的我的资料进行编辑操做,除非是管理员,这里咱们将借助Laravel提供的中间件Middleware快速实现。php
HTTP 中间件提供了一个方便的机制来过滤进入应用程序的 HTTP 请求,例如,Laravel 自己使用中间件来验证用户的身份,若是用户未经过身份验证,中间件将会把用户导向登陆页面,反之,当用户经过了身份验证,中间件将会经过此请求并接着往下执行。html
固然,除了身份验证以外,中间件也能够被用来运行各式各样的任务,CORS 中间件负责替全部即将离开程序的响应加入适当的标头。而日志中间件则能够记录全部传入应用程序的请求。laravel
Laravel 框架已经内置了一些中间件,包括维护、身份验证、CSRF 保护,等等。全部的中间件都放在app/Http/Middleware 目录内。ajax
如果但愿每一个 HTTP 请求都通过一个中间件,只要将中间件的类加入到 app/Http/Kernel.php 的 $middleware 属性清单列表中。session
// 在 App\Http\Kernel 类内... protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,];
Laravel 提供的 Auth 中间件在过滤指定动做时,若是该用户未经过身份验证,默认将会被重定向到 auth/login 登陆页面,但咱们在应用中使用的登陆页面地址是 /login,所以咱们须要对 Auth 中间件默认的重定向地址进行更改。app
app/Http/Middleware/Authenticate.php框架
<?php namespace App\Http\Middleware; // // class Authenticate { // // public function handle($request, Closure $next) { if ($this->auth->guest()) { if ($request->ajax()) { return response('Unauthorized.', 401); } else { return redirect()->guest('login'); } } return $next($request); } }
经过阅读 Auth 中间件的源码可知,Auth 中间件会先判断当前用户是否为游客(未登陆状态的用户),当用户为游客且请求方式是 ajax 时,则抛出一个 401 响应信息,若是不是经过 ajax 的方式请求,则重定向到登陆页面。最后,若是用户为已登陆状态,则接着执行下一个请求。ide
如今退出登陆,再次尝试访问 http://sample.app/users/1/edit 页面将会被重定向到登陆页面。ui
在完成对用户未登陆限制以后,咱们来研究下已登陆用户的权限验证,即只有用户本身才能编辑本身的我的信息,其余用户无权编辑。
在 Laravel 中可使用 受权策略(Policy) 来对用户的操做权限进行验证,在用户未经受权进行操做时将返回 403 异常。this
咱们可使用如下命令来生成一个名为 UserPolicy 的受权策略类文件,用于管理用户模型的受权。
$ php artisan make:policy UserPolicy
什么是受权策略呢?咱们通常在我的资料编辑时,须要验证是否为用户本身,这样才有权限修改,先查出用户的我的信息,而后再和登陆的用户ID判断是否为同一我的,而Laravel为咱们提供了一套受权机制,只需新建一个受权策略,而后将其直接调用:
$ php artisan make:policy UserPolicy
<?php namespace App\Policies; use Illuminate\Auth\Access\HandlesAuthorization; use App\Models\User; class UserPolicy { use HandlesAuthorization; public function update(User $currentUser, User $user) { return $currentUser->id === $user->id; } }
update 方法接收两个参数,第一个参数默认为当前登陆用户实例,第二个参数则为要进行受权的用户实例。当两个 id 相同时,则表明两个用户是相同用户,用户经过受权,能够接着进行下一个操做。若是 id 不相同的话,将抛出 403 异常信息来拒绝访问。
使用受权策略须要注意如下两点:
咱们并不须要检查 $currentUser 是否是 NULL。未登陆用户,框架会自动为其 全部权限 返回 false;
调用时,默认状况下,咱们 不须要 传递当前登陆用户至该方法内,由于框架会自动加载当前登陆用户(接着看下去,后面有例子);
接下来咱们还须要在 AuthServiceProvider 类中对受权策略进行设置。AuthServiceProvider 包含了一个 policies 属性,该属性用于将各类模型对应到管理它们的受权策略上。咱们须要为用户模型 User 指定受权策略 UserPolicy。
app/Providers/AuthServiceProvider.php
<?php namespace App\Providers; use Illuminate\Contracts\Auth\Access\Gate as GateContract; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use App\Models\User; use App\Policies\UserPolicy; class AuthServiceProvider extends ServiceProvider { /** * The policy mappings for the application. * * @var array */ protected $policies = [ 'App\Model' => 'App\Policies\ModelPolicy', User::class => UserPolicy::class, ]; /** * Register any application authentication / authorization services. * * @param \Illuminate\Contracts\Auth\Access\Gate $gate * @return void */ public function boot(GateContract $gate) { $this->registerPolicies($gate); // } }
受权策略定义完成以后,咱们即可以经过在用户控制器中使用 authorize 方法来验证用户受权策略。默认的 AppHttpControllersController 类包含了 Laravel 的 AuthorizesRequests trait。此 trait 提供了 authorize 方法,它能够被用于快速受权一个指定的行为,当无权限运行该行为时会抛出 HttpException。authorize 方法接收两个参数,第一个为受权策略的名称,第二个为进行受权验证的数据。
咱们须要为 edit 和 update 方法加上这行:
$this->authorize('update', $user);
书写的位置以下:
app/Http/Controllers/UsersController.php
<?php namespace App\Http\Controllers; . . . class UsersController extends Controller { . . . public function edit($id) { $user = User::findOrFail($id); $this->authorize('update', $user); return view('users.edit', compact('user')); } public function update($id, Request $request) { $this->validate($request, [ 'name' => 'required|max:50', 'password' => 'confirmed|min:6' ]); $user = User::findOrFail($id); // 受权策略判断 $this->authorize('update', $user); $data = array_filter([ 'name' => $request->name, 'password' => $request->password, ]); $user->update($data); session()->flash('success', '我的资料更新成功!'); return redirect()->route('users.show', $id); } }
如今,若是你使用 id 为 1 的用户去访问 id 为 2 的用户编辑页面,将抛出 403 异常信息。
Traits 是一种为相似 PHP 的单继承语言而准备的代码复用机制。Trait 为了减小单继承语言的限制,使开发人员可以自由地在不一样层次结构内独立的类中复用方法集
简单使用
首先,固然是声明个 Trait,PHP5.4 增长了 trait 关键字
trait first_trait { function first_method() { /* Code Here */ } function second_method() { /* Code Here */ } }
同时,若是要在 Class 中使用该 Trait,那么使用 use 关键字
class first_class { // 注意这行,声明使用 first_trait use first_trait; } $obj = new first_class(); // Executing the method from trait $obj->first_method(); // valid $obj->second_method(); // valid
trait first_trait { function first_method() { echo "method"; } } trait second_trait { function second_method() { echo "method"; } } class first_class { // now using more than one trait use first_trait, second_trait; } $obj= new first_class(); // Valid $obj->first_method(); // Print : method // Valid $obj->second_method(); // Print : method
咱们能够在 Trait 中声明须要实现的抽象方法,这样能使使用它的 Class 必须实现它
trait first_trait { function first_method() { echo "method"; } // 这里能够加入修饰符,说明调用类必须实现它 abstract public function second_method(); } class first_method { use first_trait; function second_method() { /* Code Here */ } }
Laravel中也应用了许多Trait方法
<?php namespace Illuminate\Auth\Access; trait HandlesAuthorization { /** * Create a new access response. * * @param string|null $message * @return \Illuminate\Auth\Access\Response */ protected function allow($message = null) { return new Response($message); } /** * Throws an unauthorized exception. * * @param string $message * @return void * * @throws \Illuminate\Auth\Access\UnauthorizedException */ protected function deny($message = 'This action is unauthorized.') { throw new UnauthorizedException($message); } }
Laravel中使用上边定义好的Trait方法:
AppPoliciesUserPolicy
<?php namespace App\Policies; use Illuminate\Auth\Access\HandlesAuthorization; use App\Models\User; class UserPolicy { use HandlesAuthorization; /** * Create a new policy instance. * * @return void */ public function __construct() { // } /** * 用户更新时的权限验证 * @param User $currentUser * @param User $user * @return bool */ public function update(User $currentUser, User $user) { return $currentUser->id === $user->id; } }
相关文章:
我所理解的 PHP Trait