autn / gcl-users
Laravel 用户与角色包
Requires
- php: >=5.5.9
- baum/baum: ~1.1
- doctrine/dbal: ^2.5
- laravel/framework: 5.2.*
- php-soft/laravel-array-view: 1.1.4
- tymon/jwt-auth: 0.5.*
- zizaco/entrust: dev-laravel-5
Requires (Dev)
- fzaninotto/faker: ~1.4
- mockery/mockery: 0.9.*
- phpmd/phpmd: 2.2.*
- phpspec/phpspec: ~2.1
- phpunit/phpunit: ~4.0
- squizlabs/php_codesniffer: 1.4.*@stable
- symfony/css-selector: ~3.0
- symfony/dom-crawler: ~3.0
This package is auto-updated.
Last update: 2024-09-16 16:19:46 UTC
README
本模块使用 JWTAuth 和 ENTRUST 库
- https://github.com/tymondesigns/jwt-auth (JSON Web Token)
- https://github.com/Zizaco/entrust (基于角色的权限)
- https://github.com/php-soft/laravel-users (用户管理器)
1. 安装
通过 composer 安装 - 编辑你的 composer.json
文件以添加包。
"require": { // ... "zizaco/entrust": "dev-laravel-5", "autn/gcl-users": "2.x" }
版本兼容性
然后,在终端运行 composer update
来引入它。完成此操作后,您需要在 app.php
配置文件中的 providers
数组中添加服务提供者,如下所示
'providers' => [ // ... PhpSoft\ArrayView\Providers\ArrayViewServiceProvider::class, Gcl\GclUsers\Providers\UserServiceProvider::class, Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class, Zizaco\Entrust\EntrustServiceProvider::class, Baum\Providers\BaumServiceProvider::class, ]
接下来,也在 app.php
配置文件中,在 aliases
数组下,您可能想添加门面。
'aliases' => [ // ... 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 'JWTFactory'=> Tymon\JWTAuth\Facades\JWTFactory::class, 'Entrust' => Zizaco\Entrust\EntrustFacade::class,
您可以使用以下命令发布配置
$ php artisan vendor:publish --provider="Gcl\GclUsers\Providers\UserServiceProvider"
别忘了在 jwt 配置文件中设置一个密钥!
我包含了一个辅助命令来生成密钥,如下所示
$ php artisan jwt:generate
这将生成一个新的随机密钥,它将被用于签名您的令牌。
2. 迁移和填充
现在生成迁移
$ php artisan gcl-users:migrate
它将生成 <timestamp>_entrust_setup_tables.php
迁移。您现在可以使用 artisan migrate 命令运行它
$ php artisan migrate
使用命令运行填充器
$ php artisan db:seed --class=UserModuleSeeder
注意:在使用 UserTrait
之前运行填充器,在你的现有 App\User
模型中,按照以下 3.2 步骤操作
3. 使用
3.1. 使用 JSON Web Token 进行认证
您需要将类 App\User
修改为从 Gcl\GclUsers\Models\User
继承,如下所示
namespace App; // ... use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Gcl\GclUsers\Models\User as GclUser; class User extends GclUser implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract { use Authenticatable, CanResetPassword; // ... // You need allows fill attributes as follows protected $fillable = [ 'name', 'email', 'password', 'username', 'location', 'country', 'biography', 'occupation', 'website', 'image', 'birthday', 'gender' ]; // ... }
从 app/Http/Kernel.php
中移除中间件
\App\Http\Middleware\EncryptCookies::class
\App\Http\Middleware\VerifyCsrfToken::class
在 app/Http/Kernel.php
中添加路由中间件
protected $routeMiddleware = [ // ... 'jwt.auth' => \Gcl\GclUsers\Middleware\Authenticate::class, 'jwt.refresh' => \Tymon\JWTAuth\Middleware\RefreshToken::class, ];
在 app/Http/routes.php
中添加路由
Route::post('/auth/login', '\Gcl\GclUsers\Controllers\AuthController@login'); Route::group(['middleware'=>'jwt.auth'], function() { Route::post('/auth/logout', '\Gcl\GclUsers\Controllers\AuthController@logout'); Route::get('/me', '\Gcl\GclUsers\Controllers\UserController@authenticated'); Route::patch('/me', '\Gcl\GclUsers\Controllers\UserController@update'); Route::put('/me/password', '\Gcl\GclUsers\Controllers\PasswordController@change'); }); Route::post('/passwords/forgot', '\Gcl\GclUsers\Controllers\PasswordController@forgot'); Route::post('/passwords/reset', '\Gcl\GclUsers\Controllers\PasswordController@reset'); Route::group(['middleware'=>'routePermission'], function() { Route::get('/users/trash', '\Gcl\GclUsers\Controllers\UserController@index'); Route::post('/users', '\Gcl\GclUsers\Controllers\UserController@store'); Route::get('/users/{id}', '\Gcl\GclUsers\Controllers\UserController@show'); Route::get('/users', '\Gcl\GclUsers\Controllers\UserController@index'); Route::delete('/users/{id}', '\Gcl\GclUsers\Controllers\UserController@destroy'); Route::post('/users/{id}/trash', '\Gcl\GclUsers\Controllers\UserController@moveToTrash'); Route::post('/users/{id}/restore', '\Gcl\GclUsers\Controllers\UserController@restoreFromTrash'); Route::patch('/users/{id}', '\Gcl\GclUsers\Controllers\UserController@update'); Route::post('/users/{id}/block', '\Gcl\GclUsers\Controllers\UserController@block'); Route::post('/users/{id}/unblock', '\Gcl\GclUsers\Controllers\UserController@unblock'); Route::post('/users/{id}/roles', '\Gcl\GclUsers\Controllers\UserController@assignRole'); Route::get('/users/{id}/roles', '\Gcl\GclUsers\Controllers\RoleController@indexByUser'); Route::get('/roles', '\Gcl\GclUsers\Controllers\RoleController@index'); Route::get('/roles/{id}', '\Gcl\GclUsers\Controllers\RoleController@show'); Route::post('/roles', '\Gcl\GclUsers\Controllers\RoleController@store'); Route::patch('/roles/{id}', '\Gcl\GclUsers\Controllers\RoleController@update'); Route::delete('/roles/{id}', '\Gcl\GclUsers\Controllers\RoleController@destroy'); Route::get('/nodePermission', '\Gcl\GclUsers\Controllers\NodePermissionController@index'); Route::post('/nodePermission', '\Gcl\GclUsers\Controllers\NodePermissionController@store'); Route::patch('/nodePermission/{id}', '\Gcl\GclUsers\Controllers\NodePermissionController@updateInfo'); Route::delete('/nodePermission/{id}', '\Gcl\GclUsers\Controllers\NodePermissionController@destroy'); Route::post('/nodePermission/tree', '\Gcl\GclUsers\Controllers\NodePermissionController@updateTree'); Route::get('/roles/{id}/permission', '\Gcl\GclUsers\Controllers\NodePermissionController@getRolePerm'); Route::get('/roles/{id}/allPermission', '\Gcl\GclUsers\Controllers\NodePermissionController@checkAllPerm'); Route::post('/roles/{id}/permission', '\Gcl\GclUsers\Controllers\NodePermissionController@storePermToRole'); Route::get('/nodePermission/{id}/route', '\Gcl\GclUsers\Controllers\PermissionRouteController@index'); Route::post('/nodePermission/{id}/route', '\Gcl\GclUsers\Controllers\PermissionRouteController@store'); Route::delete('/permissionRoute/{id}', '\Gcl\GclUsers\Controllers\PermissionRouteController@destroy'); Route::get('/routes', '\Gcl\GclUsers\Controllers\PermissionRouteController@getAllRoutes'); Route::get('/routesNotTree', '\Gcl\GclUsers\Controllers\PermissionRouteController@getAllRoutesNotTree'); });
注意:您可以将其添加到您的中间件组 api
Apache 似乎会丢弃非 base64 编码的用户/密码组合的授权头。因此,要修复此问题,您可以将以下内容添加到您的 apache 配置中
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
或者,您可以通过查询字符串包含令牌
http://api.mysite.com/me?token={yourtokenhere}
3.2. 基于角色的权限
在您的现有 App\User
模型中使用 UserTrait
特性。例如
namespace App; // ... use Gcl\GclUsers\Models\UserTrait; class User extends GclUser implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract { use UserTrait, Authenticatable, CanResetPassword; // add this trait to your user model // ... }
创建 Role
和 Permission
// create role admin (default this role has been created on UserModuleSeeder) $admin = new Role(); $admin->name = 'admin'; $admin->display_name = 'User Administrator'; // optional $admin->description = 'User is allowed to manage and edit other users'; // optional $admin->save(); // role attach alias $user->attachRole($admin); // parameter can be an Role object, array, or id // or eloquent's original technique $user->roles()->attach($admin->id); // id only // create permission $createPost = new NodePermission(); $createPost->name = 'create-post'; $createPost->display_name = 'Create Posts'; // optional $createPost->description = 'create new blog posts'; // optional $createPost->parent_id = 1 // optional $createPost->save(); $admin->attachPermission($createPost); // equivalent to $admin->perms()->sync(array($createPost->id));
现在我们可以通过以下方式简单地检查角色和权限
$user->hasRole('owner'); // false $user->hasRole('admin'); // true $user->can('edit-user'); // false $user->can('create-post'); // true
hasRole()
和 can()
都可以接收一个要检查的角色和权限数组
$user->hasRole(['owner', 'admin']); // true $user->can(['edit-user', 'create-post']); // true
3.3. 忘记密码
要发送忘记密码邮件,
- 您需要在
config\mail.php
中添加发件人的地址和名称,如下所示
'from' => ['address' => 'no-reply@example.com', 'name' => 'System'],
- 您需要在
resources\views\emails
文件夹中创建电子邮件视图:创建password.blade.php
文件,内容如下
<h3>You are receiving this e-mail because you requested resetting your password to domain.com</h3> Please click this URL to reset your password: <a href="http://domain.com/passwords/reset?token={{$token}}">http://domain.com/passwords/reset?token={{$token}}</a>
您可以更改此视图的内容以供使用。
另一种方法,您可以使用其他视图和配置 password.email
在 config\auth.php
'password' => [ 'email' => 'emails.password', 'table' => 'password_resets', 'expire' => 60, ],
3.4. 中间件
Gcl\GclUsers\Middleware\RoutePermission
此中间件用于根据数据库动态检查路由的权限。
在 app/Http/Kernel.php
中添加路由中间件
protected $routeMiddleware = [ // ... 'routePermission' => \Gcl\GclUsers\Middleware\RoutePermission::class, ];
使用
Route::group(['middleware'=>'routePermission'], function() { Route::post('/blog', function () { // }); });
如下所示为路由要求权限
// require permissions or roles Gcl\GclUsers\Models\RoutePermission::setRoutePermissionsRoles(2, '/blog', 'POST');
Gcl\GclUsers\Middleware\Validate
此中间件用于检查使用此包的不同应用程序中的字段验证。
在 app/Http/Kernel.php
中添加路由中间件
protected $routeMiddleware = [ // ... 'validate' => \Gcl\GclUsers\Middleware\Validate::class, ];
使用
Route::post('/user', ['middleware'=>'validate: App\Http\Validators\UserValidate', function () { // } ]);
使用 App\Http\Validators\UserValidate
,这是一个你需要在路由中声明的类。此类用于声明验证规则。
你还可以使用其他类来声明应用程序中的验证规则,但必须实现 Gcl\GclUsers\Contracts\Validator
类。
例如,我在 App\Http\Validators\UserValidate
类中声明规则如下
use Gcl\GclUsers\Contracts\Validator; /** * User Validate * * return array */ class UserValidate implements Validator { /** * Custom validator * * @return boolean */ public static function boot($request) { IlluminateValidator::extend('validate_name', function($attribute, $value, $parameters) { return $value == 'validate_name'; }, 'The name is in valid.' ); } /** * Declare rules * * @return array */ public static function rules() { return [ 'name' => 'required|max:255|validate_name', 'email' => 'required|email', 'password' => 'required|confirmed|min:6' ]; } }
在这里,你将在 rules()
函数中声明你想要验证的字段。你还可以通过在 boot()
函数中声明来自定义你想要验证的字段。