User Authentication
- Introduction
- Quick Guide to User Authentication
- Manual Verify user
- HTTP Basic Authentication
- Logout
- Social authentication
- Add custom protection
- Add custom user provider
- Event
Introduction
{tip} Want to get started quickly? Just run
php artisan make:auth
andphp artisan migrate
in a new Laravel application. Then, navigate your browser tohttp://your-app.test/register
or any other URL assigned to your application. These two commands will be responsible for building the entire authentication system!
Laravel makes implementing authentication very simple. In fact, almost all configurations are ready-made. The authentication configuration file is located at config/auth.php
and contains several well-documented options for adjusting the behavior of the authentication service.
At its core, Laravel's authentication facility consists of "Guards" and "Providers". The guard decides how to authenticate the user for each request. For example, Laravel comes with a session
protection, which uses session storage and cookies to maintain state.
The provider decides how to retrieve users from persistent storage. Laravel supports retrieving users using Eloquent and database query builder. However, you are free to define other providers based on your application's needs.
If this sounds confusing to you, don’t worry! Many applications never need to modify the default authentication configuration.
Database Notes
By default, Laravel includes an App\User
Eloquent model is in your app
directory. This model can be used with the default Eloquent authentication driver. If your application does not use Eloquent, you can use the database
authentication driver, which uses the Laravel query builder.
When generating the database schema for the App\User
model, make sure the password is at least 60 characters long. Keeping the default string length of 255 characters is a good choice.
Additionally, you should verify that the "users" (or equivalent) table contains a nullable, 100-character remember_token
string. This column will be used to store the token when the user selects the "Remember Me" option when logging into the application.
Quick Guide to User Authentication
Laravel comes with several pre-built authentication controllers located in App\Http\Controllers\Auth
namespace. RegisterController
handles new user registration, LoginController
handles authentication, ForgotPasswordController
handles email links for resetting passwords, ResetPasswordController
contains Logic to reset password. Each of these controllers uses an attribute to contain their necessary methods. For many applications, you don't need to modify these controllers at all.
Routing
Laravel provides a quick way to set up all the routes and views needed for authentication using a simple command:
php artisan make:auth
This command should be used for new applications program and will install layout views, registration and login views, and routes for all authentication endpoints. A HomeController
will also be generated to handle post-login requests for the application dashboard.
{tip} If your application does not require registration, you can disable it by deleting the newly created
RegisterController
and modifying the route declaration:Auth::routes([' register' => false]);
.
View
As mentioned in the previous section, php artisan make:auth
The command will create all views required for authentication and place them in the resources/views/auth
directory. The
make:auth
command will also create a resources/views/layouts
directory that contains the basic layout of the application. All these views use the Bootstrap CSS framework, but you are free to customize them.
Authentication
Now that the routing and views have been set up for the authentication controller, you can Register and authenticate new users! Because the controller already includes authentication logic by default to verify the user exists and save the user to the database (implemented through traits), you can now access the application in the browser.
Custom path
When users are authenticated successfully, they will be redirected to the URI /home
. You can customize it by defining the redirectTo
property in the LoginController
, RegisterController
, ResetPasswordController
, and VerificationController
controllers. Authenticated redirect location:
protected $redirectTo = '/';
Next, you should modify the handle
method in the RedirectIfAuthenticated
middleware to redirect to the new location when redirecting the user URI.
If the redirection path requires custom generation logic, you can define the redirectTo
method instead of the redirectTo
attribute:
protected function redirectTo(){ return '/path'; }
{Tip} The redirectTo method takes precedence over the redirectTo attribute.
Custom username
Laravel uses the email
field for authentication by default. If you want to use other fields, you can define a username
method in the LoginController
controller:
public function username(){ return 'username'; }
Customized Watcher
You can also customize the "Watcher" for user authentication and registration. To implement this functionality, guard
methods need to be defined in LoginController
, RegisterController
and ResetPasswordController
. This method will return a guard instance:
use Illuminate\Support\Facades\Auth;protected function guard(){ return Auth::guard('guard-name'); }
Custom verification/storage
In order to modify the form fields that new users need to fill in when registering, or customize How to store new users into the database, you can modify the RegisterController
class. This class is responsible for validating and creating new users. The
method of the RegisterController
class contains the rules for validating new users. You can customize this method as you like. The
method of RegisterController
is responsible for creating a new App\User
record in the database using Eloquent ORM. You can customize this method according to the needs of the database.
Retrieve authenticated users
You can access authenticated users through the Auth
facade :
use Illuminate\Support\Facades\Auth; // 获取当前通过认证的用户... $user = Auth::user(); // 获取当前通过认证的用户 ID... $id = Auth::id();
Alternatively, you can access the authenticated user through the Illuminate\Http\Request
instance. Don’t forget, the type-hinted class will be automatically injected into your controller method:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class ProfileController extends Controller{ /** * 更新用户资料。 * * @param Request $request * @return Response */ public function update(Request $request) { // $request->user() 返回一个认证用户实例... } }
To determine whether the current user has been authenticated
you can use ## The check
method of the #Auth facade to check whether the user has been authenticated. If authenticated,
true will be returned:
use Illuminate\Support\Facades\Auth; if (Auth::check()) { // 用户已经登录了... }
{Tip} Although you can use theProtect routing Routing middleware can be used to allow only authenticated users to access a given routing. Laravel comes with acheck
method to confirm whether the user is authenticated, the user will not be allowed to access before Before some route/controller, it is still common to use middleware to verify that the user is authenticated. For more information, check out the documentation on protected routing.
auth middleware, which is defined in
Illuminate\Auth\Middleware\Authenticate. Since this middleware is already registered in the HTTP kernel, you only need to attach this middleware to the route definition:
Route::get('profile', function () { // 只有认证过的用户可以进入... })->middleware('auth');Of course, if you use a controller, you can call it in the controller's constructor
middleware Method to append it directly to the route definition:
public function __construct(){ $this->middleware('auth'); }
Redirect unauthenticated users
When the auth
middleware detects an unauthenticated user, it will redirect the user to a directory named login
on named routes.
You can modify this behavior by modifying the redirectTo
function in the app/Http/Middleware/Authenticate.php
file:
/** * Get the path the user should be redirected to. * * @param \Illuminate\Http\Request $request * @return string */ protected function redirectTo($request){ return route('login'); }
Specify the watcher
When you add the auth
middleware to the route, you can also specify which watcher to use for user authentication. The specified guard should correspond to a key in the guards
array in the auth.php
configuration file:
public function __construct(){ $this->middleware('auth:api'); }
Login Throttling
If you use Laravel's built-in LoginController
class, the Illuminate\Foundation\Auth\ThrottlesLogins
trait is already included in the control The device was hit. By default, if a user fails to provide correct login credentials after multiple attempts, the user will not be able to try to log in again for one minute. This throttling policy is based on the uniqueness of a user's username/email address and their IP address.
Manually authenticating users
It is not necessary to use an authentication controller in Lavarel. If you choose to remove these controllers, you will need to use the Lavarel validation classes directly. Don't worry, it's easy!
You can access the Laravel service with the help of the Auth
facade, so you need to import Auth
at the beginning of the class. Let's take a look at the attempt
method:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class LoginController extends Controller{ /** * 处理身份验证尝试。 * * @param \Illuminate\Http\Request $request * * @return Response */ public function authenticate(Request $request) { $credentials = $request->only('email', 'password'); if (Auth::attempt($credentials)) { // 身份验证通过... return redirect()->intended('dashboard'); } } }
attempt
Each parameter of the method is an associative array. The array value is used to find the user in the database. In the above example, the user will be found by the value of the email
column. If the user is found, the hashed password stored in the database is compared to the password
value in the array. There is no need to hash password
, the framework automatically hashes this value before comparing it to the hashed password in the database. If the two hashes match, an authenticated session will be established for the user.
If the verification is successful, the attempt
method returns true
, otherwise it returns false
.
The intended
method in redirection will redirect the user to the URL intercepted before authentication via the authentication middleware. If the expected target does not exist, you can specify a fallback URI for this method.
Specify additional conditions
In addition to the user's email and password, you can add additional conditions to the authentication query. For example, we can verify that the user has been marked as "activated":
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) { // 用户存在,已激活且未被禁用。 }
{note} In these examples,
Access the specified guard instance
You can use the Auth
facade's guard
method to specify the guard instance you want to use. This allows you to use completely independent verifiable models or user tables to manage validation for various parts of your application.
The guard name passed to the guard
method needs to match one of the configuration items in the auth.php
configuration:
if (Auth::guard('admin')->attempt($credentials)) { // }
Logout
Users need to log out using the logout
method of the Auth
facade. It will clear the user authentication information in the user session:
Auth::logout();
Remember the user
If you want To provide "remember me" functionality in your application, you can pass a boolean value to the attempt
method as its second parameter, which will keep the user authenticated indefinitely until the user manually logs out. The user table needs to contain a remember_token
column of string type for storing tokens.
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) { // 用户被记住... }
{tip} If you use Laravel's built-in
LoginController
, the correct logic to "remember" the user is already implemented by the traits used by the controller.
If "Remember User" is enabled, you can use the viaRemember
method to determine whether the "Remember Me" cookie is used to authenticate the user:
if (Auth::viaRemember()) { // }
Other authentication methods
Verify user instance
If you want to replace an existing To log in to the application, the user can call the login
method with the user instance as its parameter. The object must implement the Illuminate\Contracts\Auth\Authenticatable
contract. The App\User
model that comes with Laravel has implemented this interface:
Auth::login($user); // 登录并「记住」给定的用户... Auth::login($user, true);
Use the following method to specify the desired guard instance:
Auth::guard('admin')->login($user);
Verify user identity by ID
You can use the loginUsingId
method to log in the user to the application by ID. This method accepts the primary key of the user whose identity you wish to authenticate:
Auth::loginUsingId(1); // 登录并「记住」给定用户... Auth::loginUsingId(1, true);
Authenticate the user's identity only once
You can use the once
method to authenticate the user in a single request The user logs into the application. Doing so will not use sessions or cookies, which means this method helps build a stateless API:
if (Auth::once($credentials)) { // }
HTTP Basic Authentication
HTTP Basic Authentication Provides a quick way to authenticate users in your application without setting up a dedicated "login" page. Before you begin, attach the auth.basic
middleware to your route. auth.basic
The middleware is already included in the Laravel framework, so you don't need to define it:
Route::get('profile', function () { // 只有认证过的用户可以进入... })->middleware('auth.basic');
After attaching the middleware to a route, it will automatically You are prompted for credentials. By default, the auth.basic
middleware uses the email
field on the user record as the "username".
FastCGI Notes
If you are using PHP FastCGI mode, HTTP basic authentication may not work properly. You need to add the following lines to your .htaccess
file:
RewriteCond %{HTTP:Authorization} ^(.+)$ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]##Stateless HTTP Basic Authentication You can also use HTTP basic authentication without setting the user identifier cookie in the session, which is especially useful for API authentication. To do this, define a middleware that will call the
onceBasic method. If the
onceBasic method does not return any response, the request can be passed further into the application:
<?php namespace App\Http\Middleware; use Illuminate\Support\Facades\Auth; class AuthenticateOnceWithBasicAuth{ /** * 处理传入的请求 * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, $next) { return Auth::onceBasic() ?: $next($request); } }Next, the routing middleware is registered and attached to the route:
Route::get('api/user', function () { // 只有认证过的用户可以进入... })->middleware('auth.basic.once');LogoutTo manually log the user out of the application, you can use the
Auth facade
logout method. This will clear the authentication information in the user's session:
use Illuminate\Support\Facades\Auth;Auth::logout();Invalidate the Session on other devicesLaravel A mechanism is also provided for invalidating and "logging off" user sessions on other devices without invalidating the session on their current device. First, you need to ensure that the
Illuminate\Session\Middleware\AuthenticateSession middleware is in the
web middleware group in your
app/Http/Kernel.php class , and is not commented out:
'web' => [ // ... \Illuminate\Session\Middleware\AuthenticateSession::class, // ... ],Then, you can use the
logoutOtherDevices method on the
Auth facade. This method requires the user to provide their current password, which your application should accept through the input form:
use Illuminate\Support\Facades\Auth; Auth::logoutOtherDevices($password);
{note} When thelogoutOtherDevices
method is called, the user's other Session will be completely disabled, meaning they will "exit" all of the watchers they were previously authenticated to.
Add a custom guard
You can define your own authentication guard using the extend
method of the Auth
facade. You should call the extend
method in the service provider. Since Laravel already comes with AuthServiceProvider
, we can put the code in that provider:
<?php namespace App\Providers; use App\Services\Auth\JwtGuard; use Illuminate\Support\Facades\Auth; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider{ /** * 注册任意应用认证/授权服务。 * * @return void */ public function boot() { $this->registerPolicies(); Auth::extend('jwt', function ($app, $name, array $config) { // 返回一个 Illuminate\Contracts\Auth\Guard 实例... return new JwtGuard(Auth::createUserProvider($config['provider'])); }); }}
As you can see in the example above, pass to extend
The callback of the method should return an instance that implements the Illuminate\Contracts\Auth\Guard
interface. This interface contains some methods that you need to implement in your custom watcher. After your custom guard is defined, you can use this guard in the guards
configuration of the auth.php
configuration file:
'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ],
Request Closure Guard
The simplest way to implement a custom authentication system based on HTTP requests is to use Auth::viaRequest
method. This method allows you to quickly define the authentication process using a single closure.
First, call the Auth::viaRequest
method in the boot
method of AuthServiceProvider
. viaRequest
The method accepts a guard name as its first parameter. This name can be any string that describes your custom watcher. The second argument passed to this method should be a closure function that receives the incoming HTTP request and returns a user instance, or null
if validation fails:
use App\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; /** * 注册任意应用认证/授权服务。 * * @return void */ public function boot(){ $this->registerPolicies(); Auth::viaRequest('custom-token', function ($request) { return User::where('token', $request->token)->first(); }); }
When you have finished customizing the guard, you can use this guard in the guards
configuration of the auth.php
configuration file:
'guards' => [ 'api' => [ 'driver' => 'custom-token', ], ],
Add a custom user provider
If you are not using a traditional relational database to store users, you will need to extend Lavarel with your own authentication user provider . You can customize the user provider using the provider
method of the Auth
facade:
<?php namespace App\Providers; use Illuminate\Support\Facades\Auth; use App\Extensions\RiakUserProvider; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider{ /** * 注册任意应用身份验证 / 授权服务Register any application authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Auth::provider('riak', function ($app, array $config) { // 返回 Illuminate\Contracts\Auth\UserProvider 实例... return new RiakUserProvider($app->make('riak.connection')); }); }}
Once registered using the provider
method, you can auth.php
Switch to the new user provider in the configuration file. First define a provider
that uses the new driver:
'providers' => [ 'users' => [ 'driver' => 'riak', ], ],
Then you can use this provider in the guards
configuration:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], ],
User Provider Contract
Illuminate\Contracts\Auth\UserProvider
The implementation is only responsible for extracting from persistent storage systems such as MySQL, Riak, etc. Illuminate\Contracts\Auth\Authenticatable
accomplish. These two interfaces allow Laravel's authentication mechanism to continue functioning regardless of how the user is stored and what type of class is used to represent it:
Let's take a lookIlluminate\Contracts\Auth\UserProvider
Contract:
<?php namespace Illuminate\Contracts\Auth; interface UserProvider { public function retrieveById($identifier); public function retrieveByToken($identifier, $token); public function updateRememberToken(Authenticatable $user, $token); public function retrieveByCredentials(array $credentials); public function validateCredentials(Authenticatable $user, array $credentials); }
retrieveById
The function usually accepts the key used to represent the class (such as the automatically incremented ID in the MySQL database) as a parameter, and obtains and returns the ## matching this ID #Authenticatable implementation. The
retrieveByToken function retrieves a user using their unique
$identifier and the "remember me" token stored in the
remember_token column. Like the previous method, it returns the
Authenticatable implementation. The
updateRememberToken method updates the
remember_token column of
$user with the new
$token. A "refresh token" is assigned when the "Remember Me" login verification is successful or when the user logs out.
retrieveByCredentials method accepts an array of credentials passed to the
Auth::attempt method when attempting to log in to the application. This method "queries" the underlying persistence store for users matching these credentials. Typically, this method runs a "where" condition based on
$credentials['username'], which should return an
Authenticatable implementation.
This method does not attempt any password verification or authentication. The
validateCredentials method should compare the given
$user to
$credentials to validate the user's identity. For example, this method should probably use
Hash::check to compare the value of
$user->getAuthPassword() with that of
$credentials['password'] value. It should return
true or
false to indicate whether the user's password is valid.
Authentication Contract
We have dissected each method of UserProvider
. Let’s take a look at the Authenticatable
contract. Remember that the user provider's retrieveById
, retrieveByToken
, and retrieveByCredentials
methods will return an instance of this interface:
<?php namespace Illuminate\Contracts\Auth; interface Authenticatable { public function getAuthIdentifierName(); public function getAuthIdentifier(); public function getAuthPassword(); public function getRememberToken(); public function setRememberToken($value); public function getRememberTokenName(); }
This interface is simple. The getAuthIdentifierName
method should return the name of the user's "primary key" column, and the getAuthIdentifier
method should return the user's "primary key". In the MySQL backend, it will be an auto-incrementing primary key. getAuthPassword
The method should return the user's hashed password. This interface allows the authentication system to always work with any User class, regardless of which ORM or abstraction storage layer is used. By default, Laravel's app
directory will contain a User
class that implements this interface. You can use this implementation example as a reference.
Events
Laravel raises a variety of events during the authentication process. Listeners for these events can be attached in EventServiceProvider
:
/** * 应用的事件监听器映射。 * * @var array */ protected $listen = [ 'Illuminate\Auth\Events\Registered' => [ 'App\Listeners\LogRegisteredUser', ], 'Illuminate\Auth\Events\Attempting' => [ 'App\Listeners\LogAuthenticationAttempt', ], 'Illuminate\Auth\Events\Authenticated' => [ 'App\Listeners\LogAuthenticated', ], 'Illuminate\Auth\Events\Login' => [ 'App\Listeners\LogSuccessfulLogin', ], 'Illuminate\Auth\Events\Failed' => [ 'App\Listeners\LogFailedLogin', ], 'Illuminate\Auth\Events\Logout' => [ 'App\Listeners\LogSuccessfulLogout', ], 'Illuminate\Auth\Events\Lockout' => [ 'App\Listeners\LogLockout', ], 'Illuminate\Auth\Events\PasswordReset' => [ 'App\Listeners\LogPasswordReset', ], ];