私はREST APIを構築し、JWT
認証と独自のロジックによる承認を行います。完全に機能しています。次に、役割と権限に基づいて動的にルートを設定したいと思います。次のようなデータベース構造があるとします。
役割:
id | name
1 | school
2 | transport
権限:
id | name | controller | routes
1 | view-class-result | ApiController | getClassResult
2 | view-student-result | ApiController | studentResult
3 | download-student-result | ApiController | donwloadSchoolTemplate
Permission_role
role_id | permission_id
1 1
1 2
1 3
ここで、データベースの役割と権限に応じてルートを作成したいと思います。
現在、私のルートは次のようです:
//All JWT authentication API goes here
Route::group(['middleware' => 'jwt.auth'], function() {
Route::get('user', 'ApiController@getAuthUser');
Route::get('invalidate', 'ApiController@invalidate');
//All authorized API goes here
Route::group(['middleware' => 'ability:school,view-class-result,true'], function() {
Route::post('classResult', 'ApiController@getClassResult');
});
Route::group(['middleware' => 'ability:school,view-student-result,true'], function() {
Route::post('studentResult', 'ApiController@studentResult');
});
Route::group(['middleware' => 'ability:school,download-student-result,true'], function() {
Route::post('getStudentExamResult', 'ApiController@downloadSchoolTemplate');
});
});
上記のルートをハードコード化したくありません。データベースからこのルートを取得するにはどうすればよいですか。以下のようなもの。しかし、それを行う方法を理解できませんでした。
ルートファイルでは、
$a = User:all();
foreach($a->roles as $value){
foreach($value->permission as $val){
Route::group(['middleware' => 'ability:{$value->name},{$val->name},true'], function() {
Route::post('{$val->controller}', '{$val->controller}@{$val->method}');
});
}
}
ありがとうございました。
最高のアイデアは、ミドルウェアパラメータcreate Middleware call CheckPermissionを使用することでした。そのミドルウェアをapp/Http/kernel.phpファイルに登録する必要があります。あなただけのコードの下をチェックする必要があります
あなたのkernel.phpファイル
protected $routeMiddleware = [
'checkPermission' => \App\Http\Middleware\CheckPermission::class,
];
CheckPermission.php
<?php
namespace App\Http\Middleware;
use Closure;
use DB;
class CheckPermission
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next,$permission_name)
{
//first check that name in your db
$permission = DB::table('Permission')->where('name',$permission_name)->first()
if($permission){
//here you have to get logged in user role
$role_id = Auth::user()->role;
## so now check permission
$check_permission = DB::table('Permission_role')->where('role_id',$role_id)->where('permission_id',$permission->id)->first();
if($check_permission){
return $next($request);
}
//if Permission not assigned for this user role show what you need
}
// if Permission name not in table then do what you need
## Ex1 : return 'Permission not in Database';
## Ex2 : return redirect()->back();
}
}
あなたのルートファイル
Route::group(['middleware' => 'jwt.auth'], function() {
Route::post('classResult', 'ApiController@getClassResult')->middleware('checkPermission:view-class-result');
Route::post('studentResult', 'ApiController@studentResult')->middleware('checkPermission:view-student-result');
Route::post('getStudentExamResult', 'ApiController@downloadSchoolTemplate')->middleware('checkPermission:download-student-result');
}
あなたのroutes.php
Route::group(['middleware' => 'jwt.auth'], function() {
Route::post('{uri}', 'AccessController@redirectURI');
});
このルートをすべてのルートの最後に追加します。
次に、AccessController
という新しいコントローラーを作成し、以下のconstructor
とmethod
を追加します。ユーザーがロールと関係を持っていると想定します。
public function __construct(Request $request)
{
$authorised_user = User::where('id', Auth::User()->id)->whereHas('role', function($query) use ($request)
{
$query->whereHas('permission', function($query) use ($request)
{
$query->where('routes', $request->route('uri'))
});
})->firstOrFail();
if( $authorised_user )
{
$permission = Permission::where('routes', $request->route('uri'))->findOrFail();
$this->middleware([ 'ability:'.$authorised_user->role()->name.','.$permission->name.',true' ]);
}
else
{
// user is not authorised. Do what ever you want
}
}
public function redirectURI($uri)
{
$permission = Permission::where('routes', $uri)->findOrFail();
return app('App\\Http\\Controllers\\'. $permission->controller )->$permission->method();
}
全体として、URLを取得し、認証されたユーザーのアクセス許可で使用可能なルートと比較します。認証されたユーザーがルートが属する権限を持っている場合、適切なミドルウェアを追加します。
最後に、redirectURI
メソッドは適切なコントローラーメソッドを呼び出し、応答を返します。
必要に応じて、コードを適切な名前空間と関係に置き換えることを忘れないでください。
これがこれに対する最良のアプローチだとは思いませんが、あなたの考え方では、この「疑似コード」を試すことができます。これが基本的な考え方を表しているといいのですが。それが意味することは:
api/studentResult
Route::group(['middleware' => 'jwt.auth'], function() {
Route::get('user', 'ApiController@getAuthUser');
Route::get('invalidate', 'ApiController@invalidate');
// Choose whatever pattern you like...
Route::post('api/{name}', ApiController::class);
});
class ApiController {
public function __construct() {
$permisions = $this->loadPersionForUser();
$this->middleware('ability', [$permisions->value1, 'whatever']);
}
public function __invoke($method) {
if (method_exists($this, $method)) {
return $this->$method();
}
}
}
このようにミドルウェアを動的にロードできるかどうかは、完全にはわかりません。もしそうなら、これはこれのための有効なアプローチかもしれません。
だからあなたができることはあなたのロール名をaccountants a valueからkey。envファイルに同じにすることです各ロール名ごとに。
近い将来変更したい場合は、。envファイルで手動で変更するか、。envファイルでphpコードライターLaravel関数の1つ。