Laravel框架 之 权限控制

本文的示例代码参考laravel-permission-demo

目录

Startup

docker run --name laravel-permission-demo -p 3306:3306 -e MYSQL_ROOT_PASSWORD=secret -d mysql:5.7.17

docker exec -i laravel-permission-demo mysql -uroot -psecret  <<< "CREATE DATABASE IF NOT EXISTS homestead DEFAULT CHARSET utf8 COLLATE utf8_general_ci;"

composer create-project laravel/laravel laravel-permission-demo && cd laravel-permission-demo

sed -i "" "s/DB_USERNAME=homestead/DB_USERNAME=root/g" .env
php artisan make:auth

php artisan migrate

php artisan route:list

laravel-permission

composer require spatie/laravel-permission

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"

php artisan migrate
php artisan make:migration seed_roles_and_permissions_data

database/migrations/*seed_roles_and_permissions_data.php
<?php

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Migrations\Migration;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;


class SeedRolesAndPermissionsData extends Migration
{
    public function up()
    {
        app()['cache']->forget('spatie.permission.cache');

        Permission::create(['name' => 'fetch_machines']);
        Permission::create(['name' => 'create_machines']);

        $projectManager = Role::create(['name' => 'project_manager']);
        $projectManager->givePermissionTo('fetch_machines');
        $projectManager->givePermissionTo('create_machines');

        $driver = Role::create(['name' => 'driver']);
        $driver->givePermissionTo('fetch_machines');
    }

    public function down()
    {
        app()['cache']->forget('spatie.permission.cache');

        $tableNames = config('permission.table_names');

        Model::unguard();
        DB::table($tableNames['role_has_permissions'])->delete();
        DB::table($tableNames['model_has_roles'])->delete();
        DB::table($tableNames['model_has_permissions'])->delete();
        DB::table($tableNames['roles'])->delete();
        DB::table($tableNames['permissions'])->delete();
        Model::reguard();
    }
}
php artisan make:seed UsersTableSeeder

vim database/seeds/UsersTableSeeder.php
<?php

use App\User;
use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    public function run()
    {
        $users = factory(User::class)
            ->times(2)
            ->make()
            ->each(function ($user, $index) {
                if ($index === 0) {
                    $user->name = 'test1';
                    $user->email = 'test1@126.com';
                } else if ($index === 1) {
                    $user->name = 'test2';
                    $user->email = 'test2@126.com';
                }
            });
        $user_array = $users->makeVisible(['password', 'remember_token'])->toArray();
        User::insert($user_array);

        $user = User::find(1);
        $user->assignRole('project_manager');

        $user = User::find(2);
        $user->assignRole('driver');
    }
}
vim database/seeds/DatabaseSeeder.php
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
         $this->call(UsersTableSeeder::class);
    }
}
vim app/User.php
<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
    use Notifiable;

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];
}
php artisan migrate:refresh --seed

Model

php artisan make:model Models/Machine --migration
vim app/Models/Machine.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Machine extends Model
{
    protected $fillable = ['name', 'project_manager_id', 'driver_id'];
}
vim database/migrations/*create_machines_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateMachinesTable extends Migration
{
    public function up()
    {
        Schema::create('machines', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->unsignedInteger('project_manager_id');
            $table->unsignedInteger('driver_id');
            $table->timestamps();

            $table->foreign('project_manager_id')
                ->references('id')
                ->on('users');
            $table->foreign('driver_id')
                ->references('id')
                ->on('users');
        });
    }

    public function down()
    {
        Schema::dropIfExists('machines');
    }
}
php artisan migrate
php artisan make:seed MachinesTableSeeder

vim database/seeds/MachinesTableSeeder.php
<?php

use App\Models\Machine;
use Illuminate\Database\Seeder;

class MachinesTableSeeder extends Seeder
{
    public function run()
    {
        $machine = new Machine();
        $machine->name = 'machine1';
        $machine->project_manager_id = '1';
        $machine->driver_id = '1';
        $machine->save();

        $machine = new Machine();
        $machine->name = 'machine2';
        $machine->project_manager_id = '1';
        $machine->driver_id = '2';
        $machine->save();
    }
}
vim database/seeds/DatabaseSeeder.php
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
         $this->call(UsersTableSeeder::class);
         $this->call(MachinesTableSeeder::class);
    }
}
php artisan migrate:refresh --seed

Route

vim routes/web.php
<?php

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

Route::get('/machines', 'MachinesController@index')->name('machines_list');
Route::get('/machines/create', 'MachinesController@create')->name('machines_create');
php artisan make:controller MachinesController

vim app/Http/Controllers/MachinesController.php
<?php

namespace App\Http\Controllers;

class MachinesController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        return 'machines_list';
    }

    public function create()
    {
        return 'machines_create';
    }
}
php artisan serve
email: test1@126.com

password: secret
machines_list
machines_create

Middleware

vim app/Http/Kernel.php
protected $routeMiddleware = [
    // ...
    'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
    'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
];
vim routes/web.php
<?php

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

Route::middleware(['permission:fetch_machines'])->group(function () {
    Route::get('/machines', 'MachinesController@index')->name('machines_list');
});
Route::middleware(['permission:create_machines'])->group(function () {
    Route::get('/machines/create', 'MachinesController@create')->name('machines_create');
});
php artisan serve
email: test1@126.com

password: secret
machines_list
machines_create

浏览器打开http://localhost:8000/home 退出当前登录账号test1

email: test2@126.com

password: secret
machines_list
Spatie \ Permission \ Exceptions \ UnauthorizedException
User does not have the right permissions.

Exception

vim app/Exceptions/Handler.php
<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Spatie\Permission\Exceptions\UnauthorizedException;

class Handler extends ExceptionHandler
{
    protected $dontReport = [
        //
    ];

    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    public function render($request, Exception $exception)
    {
        if ($exception instanceof UnauthorizedException) {
            return response()->json(['message' => 'Unauthenticated'], 401);
        }
        return parent::render($request, $exception);
    }
}
{ message: "Unauthenticated" }

Scope

vim app/Models/RoleScope.php
<?php

namespace App\Models;

use Auth;

trait RoleScope
{
    public function scopeRole($query)
    {
        $user = Auth::user();
        if (!$user->roles || !$user->roles->count()) {
            return $query;
        }
        return $query->where($user->roles[0]->name . '_id', $user->id);
    }
}
vim app/Models/Machine.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Machine extends Model
{
    use RoleScope;

    protected $fillable = ['name', 'project_manager_id', 'driver_id'];
}
vim app/Http/Controllers/MachinesController.php
<?php

namespace App\Http\Controllers;

use App\Models\Machine;

class MachinesController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        return Machine::role()->get();
    }

    public function create()
    {
        return 'machines_create';
    }
}
php artisan serve
email: test1@126.com

password: secret
[
    {
        "id": 1,
        "name": "machine1",
        "project_manager_id": 1,
        "driver_id": 1,
        "created_at": "2018-07-24 02:22:38",
        "updated_at": "2018-07-24 02:22:38"
    },
    {
        "id": 2,
        "name": "machine2",
        "project_manager_id": 1,
        "driver_id": 2,
        "created_at": "2018-07-24 02:22:38",
        "updated_at": "2018-07-24 02:22:38"
    }
]

浏览器打开http://localhost:8000/home 退出当前登录账号test1

email: test2@126.com

password: secret
[
    {
        "id": 2,
        "name": "machine2",
        "project_manager_id": 1,
        "driver_id": 2,
        "created_at": "2018-07-24 02:22:38",
        "updated_at": "2018-07-24 02:22:38"
    }
]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容