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;
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, ], ], ], ];
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)
HTTP basic authentication, the authentication information is placed in the request header; subsequent requests are accessed through sessionId;
public function basic($field = 'email', $extraConditions = [])
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 = [])
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, ], ], ]
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; }
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); }
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 意味没有权限 }, ...... );
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; } }
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, ];
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));
推荐教程:《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!