Home > PHP Framework > Laravel > Laravel's Auth module usage

Laravel's Auth module usage

Guanhui
Release: 2020-05-02 11:29:27
forward
3874 people have browsed it

This article is based on the analysis and writing of the Auth module code of Laravel 5.4 version;

Module composition

The Auth module is functionally divided into two parts: user authentication and permission management In terms of file composition, the Illuminate\Auth\Passwords directory is a small module for password reset or forgotten password processing. Illuminate\Auth is the module responsible for user authentication and authority management. Illuminate\Foundation\Auth provides login and modification functions. Specific logic implementation of a system such as password and reset password; the following figure shows the relationship between the various files of the Auth module and a brief explanation;

Laravels Auth module usage

User Authentication

HTTP itself is stateless. Usually in the process of system interaction, the account or Token identification is used to determine the authenticated user;

Configuration file interpretation

return [
    'defaults' => [
        'guard' => 'web',
        ...
    ],
    'guards' => [  
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [    
            'driver' => 'token', 
            'provider' => 'users',
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ], 
    ],
], 
];
Copy after login

From below Go up and understand;

providers is the interface that provides user data, and the driver object and target object must be marked; here, the key name users is the name of a set of providers, driven by eloquent, and modal is App\User: :class;

The guards part is configured for the authentication management part; there are two authentication methods, one is called web, and the other is api; web authentication is based on Session interaction, and the user ID is obtained according to the sessionId. In users This provider queries the user; api authentication is based on token value interaction, and also uses the users provider;

defaults item shows that web authentication is used by default;

Authentication

Session binding authentication information:

// $credentials数组存放认证条件,比如邮箱或者用户名、密码
// $remember 表示是否要记住,生成 `remember_token`
public function attempt(array $credentials = [], $remember = false) 
 
public function login(AuthenticatableContract $user, $remember = false)
 
public function loginUsingId($id, $remember = false)
Copy after login

HTTP basic authentication, the authentication information is placed in the request header; subsequent requests are accessed through sessionId;

public function basic($field = 'email', $extraConditions = [])
Copy after login

is only authenticated in the current session, Authentication information is not recorded in the session:

public function once(array $credentials = [])
public function onceUsingId($id)
public function onceBasic($field = 'email', $extraConditions = [])
Copy after login

During the authentication process (including registration, forgotten password), the defined events are as follows:

Attempting Attempt to verify the event

Authenticated Verification passed Event

Failed Verification failed event

Lockout The number of failures exceeds the limit, lock the request to access again Event

Logi Event called when logging in successfully through 'remember_token'

Logout User exit event

Registered User registration event

There are some other authentication methods:

Check whether there is an authenticated user: Auth::check()

Get the current authenticated user: Auth::user()

Exit the system: Auth::logout()

Password processing

Configuration interpretation

return [
    'defaults' => [
        'passwords' => 'users',
        ...
    ],
    
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],
]
Copy after login

Look at the configuration from bottom to top;

The passwords array is the configuration for resetting the password; users is the alias of the configuration scheme, which contains three elements: provider (provides the user's scheme, which is the above providers Array), table (table that stores reset password tokens), expire (token expiration time)

The default item will set the default passwords reset scheme;

Reset passwords Calling and Implementation

First look at how Laravel's reset password function is implemented:

public function reset(array $credentials, Closure $callback) {
    // 验证用户名、密码和 token 是否有效
    $user = $this->validateReset($credentials);
    if (! $user instanceof CanResetPasswordContract) {
         return $user;
    }    
    
    $password = $credentials['password'];
    // 回调函数执行修改密码,及持久化存储
    $callback($user, $password);
    // 删除重置密码时持久化存储保存的 token
    $this->tokens->delete($user);
    return static::PASSWORD_RESET;
}
Copy after login

Then look at how the reset password module encapsulated by the Foundation\Auth module is called :

// 暴露的重置密码 API
public function reset(Request $request)   {
    // 验证请求参数 token、email、password、password_confirmation
    $this->validate($request, $this->rules(), $this->validationErrorMessages());
    // 调用重置密码的方法,第二个参数是回调,做一些持久化存储工作
    $response = $this->broker()->reset(
        $this->credentials($request), function ($user, $password) {
        $this->resetPassword($user, $password);
        }
    );
    // 封装 Response
    return $response == Password::PASSWORD_RESET
        ? $this->sendResetResponse($response)
        : $this->sendResetFailedResponse($request, $response);
}
// 获取重置密码时的请求参数
protected function credentials(Request $request)  {
    return $request->only(
        'email', 'password', 'password_confirmation', 'token'
    );
}
// 重置密码的真实性验证后,进行的持久化工作
protected function resetPassword($user, $password) {
    // 修改后的密码、重新生成 remember_token
    $user->forceFill([
        'password' => bcrypt($password),
        'remember_token' => Str::random(60),
    ])->save();
    // session 中的用户信息也进行重新赋值                                     
    $this->guard()->login($user);
}
Copy after login

The general process of "Forgot Password=> Send Email=> Reset Password" is as follows:

Click "Forgot Password", jump to "Forgot Password" through routing configuration Page, there is a field "Email to be sent" on the page to be filled in;

Verify whether the "Email to be sent" exists in the database. If it exists, send a password reset email to the mailbox;

There is a link in the reset password email (clicking it will bring the token to the password change page), and the database will save the hash-encrypted value of this token;

Fill in the "email", After the three fields of "Password" and "Confirm Password", bring the token to access the reset password API. The homepage determines the three fields of email, password, and confirm password, and then verifies whether the token is valid; if so, the reset is successful;

Permission management

Permission management relies on an array variable abilities maintained in the memory space to maintain. The structure is as follows:

$abilities = array(
    '定义的动作名,比如以路由的 as 名(common.dashboard.list)' => function($user) {
        // 方法的参数,第一位是 $user, 当前 user, 后面的参数可以自行决定
        return true;  // 返回 true 意味有权限, false 意味没有权限
    },
    ......
);
Copy after login

But only using $abilities will It is too cumbersome to use the defined part of the code to gather together, so the policy strategy class appears;

The policy strategy class defines the corresponding relationship between a group of entities and entity permission classes, for example, take the article as an example:

There is a Modal entity class called Post. You can define a PostPolicy permission class for this entity class. Define some actions as method names in this permission class;

class PostPolicy {
    // update 权限,文章作者才可以修改
    public function update(User $user, Post $post) {
        return $user->id === $post->user_id;
    }
}
Copy after login

Then register it in the ServiceProvider so that the system knows , if the class you want to check is a Post object, plus the action name you gave, the system will find the corresponding method of the PostPolicy class;

protected $policies = [
    Post::class => PostPolicy::class,
];
Copy after login

How to call it?

For permissions defined in the abilities array:

Whether the current user has common.dashboard.list permissions: Gate::allows('common.dashboard.list')

Whether the current user has common.dashboard.list permissions:! Gate::denies('common.dashboard.list')

Whether the current user has common.dashboard.list permissions: $request->user() ->can('common.dashboard.list')

Whether the current user has common.dashboard.list permissions:! $request->user()->cannot('common.dashboard.list ')

指定用户是否具备common.dashboard.list权限:Gate::forUser($user)->allows('common.dashboard.list')

对于policy策略类调用的权限:

当前用户是否可以修改文章(Gate 调用):Gate::allows('update', $post)

当前用户是否可以修改文章(user 调用):$user->can('update', $post)

当前用户是否可以修改文章(用帮助函数):policy($post)->update($user, $post)

当前用户是否可以修改文章(Controller 类方法中调用):$this->authorize('update', $post);

当前用户是否可以修改文章(Controller 类同名方法中调用):$this->authorize($post);

指定用户是否可以修改文章(Controller 类方法中调用):$this->authorizeForUser($user, 'update', $post);

有用的技巧

获取当前系统注册的权限,包括两部分abilities和policies数组内容,代码如下:

$gate = app(\Illuminate\Contracts\Auth\Access\Gate::class);
$reflection_gate = new ReflectionClass($gate);
$policies = $reflection_gate->getProperty('policies');
$policies->setAccessible(true);
// 获取当前注册的 policies 数组
dump($policies->getValue($gate));
                                                                                                        
$abilities = $reflection_gate->getProperty('abilities');                                       
$abilities->setAccessible(true);
// 获取当前注册的 abilities 数组
dump($abilities->getValue($gate));
Copy after login

推荐教程:《Laravel教程

The above is the detailed content of Laravel's Auth module usage. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:segmentfault.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template