本記事の例ではLaravel5の権限管理の実装方法を説明しています。参考のために皆さんと共有してください。詳細は次のとおりです:
パーミッション管理についての考え
最近、laravel を使用してバックエンドを設計したのですが、バックエンドにはパーミッション管理が必要です。権限管理は基本的に 2 つの部分に分かれており、最初に認証、次に権限です。認証部分は非常に簡単に実行できます。つまり、管理者がログインしてセッションを記録します。 Laravel にはこれを実装するための Auth も付属しています。一番面倒なのは権限認証です。
権限認証とは本質的には、誰が何を管理する権限を持っているかを意味します。ユーザー ディメンションでは、権限管理の粒度を 1 人のユーザーにすることも、ユーザーがグループ化されている場合は、1 人のユーザーを複数のグループに含めることもできます。 ?一方、何かを管理する場合、この物は物という次元を持ちます。ページは物であり、ページ上の要素も物です。さらに広く言えば、機能も物です。したがって、権限管理で最も重要なことは、これら 2 つの次元の粒度を確認することです。これはもはや技術的な問題ではなく、議論する必要があります。
上記の考え方に基づいて、今回私がやりたい権限管理はユーザー次元の個人に基づいたものになります。ただ、権限は人それぞれ異なります。東西次元ではルートを最小単位、つまり単一ルートに対して権限管理を設定します。
次の考え方は、アクセス許可をマークするために使用するものです。ビット、文字、または整数を使用できます。その後、1. キャラクターが理解しやすく、データベースで検索しやすいこと、2. 特定の権限に基づいてこの権限を持つ人物を検索する必要がないこと、の 2 つの点を考慮してキャラクターを選択しました。ビットを使用する逆検索の必要はなく、タイプ全体などはほとんど意味がありません。
次に、laravelと組み合わせる方法を考えます。 ルートごとにアクセス許可を設定する必要があるので、当然laravelのroute.phpのルーティング管理で設定できればと思います。最善の方法は、Route::get 中に権限を設定するパラメーターを用意することです。この利点は、権限設定が簡単であることです。ルーティングを決めるときに都合よくパーミッションコントロールを書きました。欠点は、laravel ルーティングの 3 つのメソッドのうち 1 つしか記述できないことも明らかであることです。これは Route::(メソッド) です。
基本的には決定を下して開始します。
ルーティングの設計
基本的なルーティングは次のとおりです
Route::post('/admin/validate', ['uses' => 'AdminController@postValidate', 'permissions'=>['admin.validate', 'admin.index']]);
ここで、基本的なルーティング アクションが設定された後、アクセス許可属性が設定されます。この属性は、たとえば投稿リクエストであるため、配列として設計されています。特定のページでトリガーされ、別のページでもトリガーされる可能性がある場合、この投稿リクエストには両方のページのルーティング権限が必要です。
ここでは、admin.validate の権限制御を使用します。このようにして、権限をグループ化できます。データベースには、[admin] => [ という 2 次元配列が保存されます。 'validate' , 'index']; 一般に、背景表示には 2 つの次元があり、1 つはヘッドのタブ バーです。左側のナビゲーション バー、つまりこの 2 次元の配列と、背景のタブおよびナビゲーション列の間に 1 対 1 の対応関係があります。
ミドルウェアの設計
さて、ミドルウェアを終了し、このミドルウェアを使用するようにすべてのルートを設定します
<?php namespace App\Http\Middleware; use Illuminate\Support\Facades\Session; use Closure; class Permission { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $permits = $this->getPermission($request); $admin = \App\Http\Middleware\Authenticate::getAuthUser(); // 只要有一个有权限,就可以进入这个请求 foreach ($permits as $permit) { if ($permit == '*') { return $next($request); } if ($admin->hasPermission($permit)) { return $next($request); } } echo "没有权限,请联系管理员";exit; } // 获取当前路由需要的权限 public function getPermission($request) { $actions = $request->route()->getAction(); if (empty($actions['permissions'])) { echo "路由没有设置权限";exit; } return $actions['permissions']; } }
ここで最も重要なことは、$request->route()-> ;getAction() からの getPermission 関数です。 ) を使用して、このルートのアクション定義を取得し、次に、route.php で定義されているルートの権限を権限フィールドから取得します。
その後、上記のミドルウェアは次のようになります:
admin−>hasPermission(admin−>hasPermission(permit);
これにはモデルの設計が含まれます。
モデル設計
<?php namespace App\Models\Admin; use App\Models\Model as BaseModel; class Admin extends BaseModel { protected $table = 'admin'; // 判断是否有某个权限 public function hasPermission($permission) { $permission_db = $this->permissions; if(in_array($permission, $permission_db)) { return true; } return false; } // permission 是一个二维数组 public function getPermissionsAttribute($value) { if (empty($value)) { return []; } $data = json_decode($value, true); $ret = []; foreach ($data as $key => $value) { $ret[] = $key; foreach ($value as $value2) { $ret[] = "{$key}.{$value2}"; } } return array_unique($ret); } // 全局设置permission public function setPermissionsAttribute($value) { $ret = []; foreach ($value as $item) { $keys = explode('.', $item); if (count($keys) != 2) { continue; } $ret[$keys[0]][] = $keys[1]; } $this->attributes['permissions'] = json_encode($ret); } }
データベースに二次元配列をjsonとして保存し、laravelのAttributeのgetメソッドとsetメソッドを使ってデータベース内のjsonと外部プログラムロジックとの接続を完了します。その後、hasPermission は非常に簡単に思えます。in_array を直接判断するだけでOKです。
フォローアップ
この権限認証のロジックは明確になります。次に、ページ上のタブまたはナビゲーションを異なる権限を持つユーザーに表示する必要がある場合は、ビュー
@if ($admin->hasPermission('admin.index')) @endif
で判断するだけで、ユーザーがタブを表示できるかどうかを判断できます。
概要
これはユーザー権限の実装はそれほど複雑ではありませんが、バックグラウンドのニーズのほとんどを満たすことができると思います。もちろん、最適化できる点はたくさんあるかもしれません。たとえば、hasPermission が nosql または pg に格納されている場合、直接 DB リクエストが存在するかどうかを判断できますか?許可などは?