Laravel101:实现简单身份验证系统的分步指南
#教程 #php #laravel #laravel101

在本教程中,我们将引导您完成在您的应用程序中手动实现强大的身份验证系统的过程。

在Laravel生态系统中,有许多实施身份验证的方法,从基于会话到基于API的身份验证,以及从Sanctum等轻量级软件包到更复杂的Passport。此外,还有一些方便的入门套件,例如BreezeJetstream,它们提供了简化的起点。但是,出于本初学者教程的目的,我们将专注于实现尽可能简单的简单身份验证系统。


让我们从注册用户开始。

要在单独的目录中创建我们的控制器,请使用以下命令:

php artisan make:controller Auth/RegisterController

在此控制器内部,我们需要两个功能。一个功能负责显示视图,而另一个功能处理控制器的逻辑。

遵循REST架构,我们需要一种创建方法来显示注册视图和商店方法来处理注册请求:

class RegisterController extends Controller
{
    public function create()
    {
        return view('auth.register');
    }

    public function store()
    {
    }
}

然后,我开发了一个简单的用户表格,其中包括名称,电子邮件和密码输入的字段:

Image description

此表单只有一个简单的布局layout.auth,而没有我们的磁带。此外,我已经将所有身份验证表单放入单独的Directory resources/views/auth

现在,让我们返回我们的路线并定义用户注册的路线。

Route::get("/register", [RegisterController::class, 'create'])->name('register');
Route::post("/register", [RegisterController::class, 'store'])->name('register.store');

接下来,我们需要创建一个可能看起来像Bellow的请求:

class RegisterRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'name' => 'required|min:3',
            'email' => "required|email|unique:users,eamil",
            'password' => "required|min:4|max:20"
        ];
    }
}

email规则已适当,以确保提供的电子邮件地址遵循适当的电子邮件格式。 unique规则用于确保以前尚未使用过的电子邮件。

不,我们可以简单地在我们的商店功能中使用它:

public function store(RegisterRequest $request)
{
    $user = User::create($request->validated());

    Auth::login($user);

    return redirect("/tasks");
}

在这里,我使用一个名为Auth的很棒的类,在创建的用户中提供简单的登录。此外,还有一个全球定义的辅助功能,例如auth(),您可以使用:auth()->login($user)

现在,让我们玩得开心。返回到任务存储功能,然后尝试检索应用程序中当前登录的用户。为此,我们可以使用dd

Auth::user()

// or 
auth()->user()

// or 

$request->user()

在这里如何做:

Image description

惊人!这意味着我们的用户现在已成功登录!

在使用模型的创建功能时,您需要注意的另一件事是质量分配问题。

如果您查看使用Laravel创建的用户模型类,则默认情况下处理此问题:

protected $fillable = [
    'name',
    'email',
    'password',
];

protected $hidden = [
    'password',
    'remember_token',
];

protected $casts = [
    'email_verified_at' => 'datetime',
    'password' => 'hashed',
];

您可以在代码中看到,密码通过铸造转换为哈希。这是将密码存储在数据库中的安全且有用的方法。

现在,如果您想以不同的方式使用自己的哈希方法怎么办?好吧,您可以在我们的请求课中进行。就在传递数据之前,请记住所有过程在验证后发生,并且仅通过重写验证的方法而发生:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Hash;

class RegisterRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'name' => "required|min:3",
            'email' => "required|email|unique:users,eamil",
            'password' => "required|min:4|max:20"
        ];
    }

    public function validated($key = null, $default = null)
    {
        return array_merge($this->validator->validated(), [
            'password' => Hash::make(request('password'))
        ]);
    }
}

Laravel Hash立面使用BCrypt和Argon2算法提供安全的哈希。有关详细说明,您可以参考官方Laravel documentation

现在,让我们返回我们的注册表控制器并将所有内容整合在一起:

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Http\Requests\RegisterRequest;
use App\Models\User;

class RegisterController extends Controller
{
    public function create()
    {
        return view('auth.register');
    }

    public function store(RegisterRequest $request)
    {
        $user = User::create($request->validated());

        auth()->login($user);

        return redirect("/tasks");
    }
}

真的很清楚,但是在现实世界中,在创建用户后,我们通常向用户发送验证电子邮件。但是,就目前而言,让我们保持简单并在接下来的课程中介绍这一点。好吧,现在让我们开始进入登录控制器:

php artisan make:controller Auth/LoginController

然后添加路由:

Route::get('login', [LoginController::class, 'create'])->name('login');
Route::post('login', [LoginController::class, 'store'])->name('login.store');

就像在寄存器控制器中一样,我们需要在登录控制器中创建一个函数以显示我们的登录视图,我从寄存器表单中保持简单:

Image description

这是我们的LoginRequest

class LoginRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'email' => 'required|email',
            'password' => 'required'
        ];
    }
}

终于让我们回到我们的登录控制器。

在创建登录系统时,我们需要遵循几个步骤。首先,我们检查用户是否存在于我们的数据库中。然后,我们验证输入密码是否匹配我们记录中存储的哈希密码。如果所有内容都签出并且用户存在,我们将为他们生成一个会话并授予对应用程序的访问。

您可以自己处理所有方案,请在Auth立场中使用另一个称为attempt的辅助功能,以照顾所有这些任务。它非常简单。我们只需要通过用户的凭据,然后处理其余的:

class LoginController extends Controller
{
    public function create()
    {
        return view('auth.login');
    }

    public function store(LoginRequest $request)
    {
        if (auth()->attempt($request->validated())) {
            return redirect()->intended('/tasks');
        }

        return back();
    }
}

您可以简单地使用上面的代码,但是如果要处理异常并显示错误消息,则可以使用称为withErrors的辅助函数。只需修改代码如下:

public function store(LoginRequest $request)
{
    if (auth()->attempt($request->validated())) {
        return redirect()->intended('/tasks');
    }

    return back()
        ->withErrors([
            'email' => 'The provided credentials do not match our records.',
        ]);
}

当然!如果您想用预填充的电子邮件值返回视图,则可以使用withInput函数。您可以做到这一点:

return back()
    ->withInput($request->only('email'))
    ->withErrors([
        'email' => 'The provided credentials do not match our records.',
    ]);

这就是结果:

Image description

好吧,我们的下一个任务是最终确定身份验证过程,并专注于实现注销功能。首先,我们将创建一个控制器:

php artisan make:controller Auth/LogoutController

并确保正确定义其路线:

Route::post('logout', LogoutController::class)->name('logout');

由于我们在控制器中只有一个函数,因此我建议使用一种不可看管的方法:

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;

class LogoutController extends Controller
{
    public function __invoke()
    {
        auth()->logout();

        return redirect('/login');
    }
}

这真的很容易!现在,让我们创建注销视图。这是一个带有按钮的简单表单,您可以单击以提交注销请求:

<form method="POST" action={{ route('logout') }}>
    @csrf
    <button type="submit">Logout</button>
</form>

我们如何在应用程序中使用此视图?我们什么时候应该避免使用它?

当前,Navbar仅显示登录和注册的选项。当用户未经授权时,我们需要在用户登录时显示注销视图。

为了实现这一目标,我们在刀片中具有两个功能。第一个Auth用于专门针对身份验证的用户显示内容,而第二位访客专门针对尚未授权的来宾用户或用户:

Image description

是!

一个重要的一点是,我们不希望客人可以访问任务资源。此外,我们希望只能访问授权用户的注销请求。

在即将到来的课程中,我们将详细探讨中间件。但是目前,让我们简要提及它包含在达到预期端点之前检查当前请求的规则。在我们的情况下,我们检查当前请求是否由授权用户提出,如果没有,我们要返回403例外。

为了实现此目标,我们可以使用auth中间件。 Laravel提供了专门将中间件添加到路线的功能。这是一个例子:

Route::post('logout', LogoutController::class)->middleware('auth');

此外,我们可以将多个路线分组在一起,并将相同的中间件应用于所有路线。这是一个例子:

Route::group(['middleware' => 'auth'], function () {
    // Add your protected routes here
});

现在,让我们继续进入我们的Web路线,并将注销和任务资源添加到组:

Route::group(['middleware' => 'auth'], function () {
    Route::resource('tasks', TaskController::class);
    Route::post('logout', LogoutController::class)->name('logout');
});

出色的工作!我们已经成功地在Laravel实施了授权系统,这确实很简单明了。虽然我们可以添加更多功能,但现在让它保持简单。

您可以在repo中找到本系列教程的项目代码。

快乐编码!