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
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在这个类中增加getJWTIdentifier
和getJWTCustomClaims
方法。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号称最优雅的框架,但是内部逻辑复杂难懂。
本文由于笔者能力有限,不足之处欢迎留言探讨。