這一節咱們將給相關的動做頁面添加權限,如已經登陸的用戶將不會看到註冊、登陸按鈕,更不會對別人的我的資料進行編輯操做,除非是管理員,這裏咱們將藉助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