laravel自带用户认证基本满足简单业务需求,如果要开发API接口则需要引入jwt认证组件。jwt组件的配置参考JWT 完整使用详解, 本文主要记录下围绕API与JWT认证一些使用技巧。

0x1 自定义认证

如果用户认证使用一些三方的认证服务,应该如何处理呢?Laravel提供自定义的认证的入口,通过Provider形式替代原有的认证逻辑。

  • 注册自定义认证方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #app/Providers/AuthServiceProvider.php
    class AuthServiceProvider extends ServiceProvider
    {

    //省略...

    /**
    * Register any authentication / authorization services.
    *
    * @return void
    */
    public function boot()
    {
    $this->registerPolicies();

    //注册DIYUserServiceProvider
    Auth::provider("DIY", function($app, array $config){
    return new DIYUserServiceProvider($app);
    });
    }
    }
  • 修复配置:

    1
    2
    3
    4
    5
    6
    #config/auth.php
    'providers' => [
    'users' => [
    'driver' => 'DIY',
    ],
    ],
  • 生成provider文件

    1
    php artisan make:provider DIYUserServiceProvider
  • 实现DIYUserServiceProvider方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    #app/Providers/DIYUserServiceProvider.php
    <?php
    namespace App\Providers;
    use Illuminate\Contracts\Auth\UserProvider;
    use Illuminate\Support\ServiceProvider;
    use Illuminate\Contracts\Auth\Authenticatable as UserContract;
    use App\User;
    use App\Services\DIYUserService;

    class DIYUserServiceProvider extends ServiceProvider implements UserProvider
    {
    /**
    * Retrieve a user by their unique identifier.
    *
    * @param mixed $identifier
    * @return \Illuminate\Contracts\Auth\Authenticatable|null
    */
    public function retrieveById($identifier)
    {
    // 根据认证信息获取用户信息
    $user = [];

    //App\User对象增加Model属性attributes
    return new User(['attributes' => $user]);
    }

    /**
    * Retrieve a user by their unique identifier and "remember me" token.
    *
    * @param mixed $identifier
    * @param string $token
    * @return \Illuminate\Contracts\Auth\Authenticatable|null
    */
    public function retrieveByToken($identifier, $token)
    {
    return new User($identifier);
    }

    /**
    * Update the "remember me" token for the given user in storage.
    *
    * @param \Illuminate\Contracts\Auth\Authenticatable $user
    * @param string $token
    * @return void
    */
    public function updateRememberToken(UserContract $user, $credentials)
    {

    }

    /**
    * Retrieve a user by the given credentials.
    *
    * @param array $credentials
    * @return \Illuminate\Contracts\Auth\Authenticatable|null
    */
    public function retrieveByCredentials(array $credentials)
    {
    $user = new User($credentials);
    return $user;
    }

    /**
    * Validate a user against the given credentials.
    *
    * @param \Illuminate\Contracts\Auth\Authenticatable $user
    * @param array $credentials
    * @return bool
    */
    public function validateCredentials(UserContract $user, array $credentials)
    {
    $username = $credentials['email'];
    $password = $credentials['password'];

    // 实现用户认证
    return DIYUserService::auth($username, $password);
    }

    }

  • User模型
    认证方法调用过程中都会使用到App\User这个类文件,jwt在这个类中增加getJWTIdentifiergetJWTCustomClaims方法。DIYUserServiceProvider方法需要将部分认证信息赋予到User类。在后续使用Laravel-permission组件时也需要增加特定方法。

0x2 API鉴权

业务模块不同,用户角色不同可以通过laravel-permission权限组件完成对用户接口调用权限的识别。laravel-permission组件是entrust组件的替代品,也是通过role、permission和model对用户权限控制。

laravel-permission组件:

  • 基础使用
    1
    2
    3
    4
    5
    6
    7
    8
    #创建角色、权限
    $role = Role::create(['name' => 'admin']);
    $permissions = [
    Permission::create(['name' => 'user-manage']),
    Permission::create(['name' => 'role-manage']),
    ];

    $role->syncPermissions($permissions);
  • API限制
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #路由配置
    Route::group(['middleware' => 'role:admin'], function () {
    //...
    });

    #User类实现判断方法(App\User.php)
    #该方法需要单独添加, v5.8版本中没有hasAnyRole该方法
    public function hasAnyRole($roles)
    {
    $user = $this->getAttribute('attributes');

    foreach ($roles as $role)
    {
    if ($role !== $user['roles'])
    {
    return false;
    }
    }

    return true;
    }

0x3 总结

laravel的生态系统丰富,各种各样组件都存在;使用不同的组件排列组合实现不同的功能,虽然laravel号称最优雅的框架,但是内部逻辑复杂难懂。

本文由于笔者能力有限,不足之处欢迎留言探讨。

0x4 参考

laravel用户认证文档
laravel-permission文档

评论