Ich baue REST API mit JWT
Authentifizierung und Autorisierung mit eigener Logik. Es funktioniert perfekt. Jetzt möchte ich die Routen dynamisch basierend auf Rollen und Berechtigungen festlegen. Angenommen, ich habe eine Datenbankstruktur wie:
Rolle:
id | name
1 | school
2 | transport
Berechtigungen:
id | name | controller | routes
1 | view-class-result | ApiController | getClassResult
2 | view-student-result | ApiController | studentResult
3 | download-student-result | ApiController | donwloadSchoolTemplate
Berechtigungsrolle
role_id | permission_id
1 1
1 2
1 3
Jetzt möchte ich Routen nach Rollen und Berechtigungen in der Datenbank erstellen.
Derzeit scheinen meine Routen wie folgt zu sein:
//All JWT authentication API goes here
Route::group(['middleware' => 'jwt.auth'], function() {
Route::get('user', '[email protected]');
Route::get('invalidate', '[email protected]');
//All authorized API goes here
Route::group(['middleware' => 'ability:school,view-class-result,true'], function() {
Route::post('classResult', '[email protected]');
});
Route::group(['middleware' => 'ability:school,view-student-result,true'], function() {
Route::post('studentResult', '[email protected]');
});
Route::group(['middleware' => 'ability:school,download-student-result,true'], function() {
Route::post('getStudentExamResult', '[email protected]');
});
});
Ich möchte nicht, dass die obigen Routen hart codiert sind. Wie bekomme ich diese Routen aus der Datenbank? Etwas wie unten. Aber ich konnte keine Idee bekommen, wie es geht.
In der Routendatei
$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}');
});
}
}
Vielen Dank.
Die beste Idee war, den Middleware-Parameter Create Middleware call CheckPermission zu verwenden. Dann müssen Sie diese Middleware in Ihrer app/Http/kernel.php -Datei registrieren
Ihre kernel.php datei
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();
}
}
Ihre Route Datei
Route::group(['middleware' => 'jwt.auth'], function() {
Route::post('classResult', '[email protected]')->middleware('checkPermission:view-class-result');
Route::post('studentResult', '[email protected]')->middleware('checkPermission:view-student-result');
Route::post('getStudentExamResult', '[email protected]')->middleware('checkPermission:download-student-result');
}
In Ihrem routes.php
Route::group(['middleware' => 'jwt.auth'], function() {
Route::post('{uri}', '[email protected]');
});
Fügen Sie diese Route am Ende aller Routen hinzu.
Erstellen Sie nun einen neuen Controller mit dem Namen AccessController
und fügen Sie ihm die folgenden constructor
und method
hinzu Angenommen, der Benutzer hat eine Beziehung zu Rollen.
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();
}
Im Allgemeinen wird die URL abgerufen und mit den verfügbaren Routen in den Berechtigungen des authentifizierten Benutzers verglichen. Wenn der authentifizierte Benutzer die Berechtigung besitzt, zu der die Route gehört, fügen Sie die entsprechende Middleware hinzu.
Schließlich ruft die Methode redirectURI
die entsprechende Controller-Methode auf und gibt die Antwort zurück.
Denken Sie daran, den Code bei Bedarf durch geeignete Namensräume und Beziehungen zu ersetzen.
Ich bezweifle zwar, dass dies der beste Ansatz ist, aber in Ihrer Denkweise könnten Sie diesen "Pseudo-Code" ausprobieren. Ich hoffe, das drückt die Grundidee aus. Was das bedeutet, ist:
api/studentResult
Route::group(['middleware' => 'jwt.auth'], function() {
Route::get('user', '[email protected]');
Route::get('invalidate', '[email protected]');
// 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();
}
}
}
Ich bin mir nicht ganz sicher, ob Sie Ihre Middleware auf diese Weise dynamisch laden können. Wenn ja, könnte dies ein gültiger Ansatz sein.
Sie können also Ihren Rollennamen accountants a value to key in der Datei .env angeben und für jeden Rollennamen gleich sein.
Falls Sie es in naher Zukunft ändern möchten, können Sie es manuell in der Datei .env ändern oder Änderungen in der Datei .env über php code writtern an einem Ihrer Browser vornehmen Laravel Funktion .