Laravel 7 + React.js 如何使用 Sanctum 做认证,第一部分

作者: hedeqiang

发布时间: 2020-04-26 16:05:29

file

我选择构建Web应用程序的技术堆栈是前端的React和后端的Laravel。 这种方法的挑战之一涉及对用户进行身份验证,以便数据库资源仅对授权个人可用。 由于Laravel 7中已添加[Sanctum](https://laravel.com/docs/7.x/sanctum) 软件包,因此此任务更加简单。

为了展示其工作原理,我创建了一个由三部分组成的简单应用程序

  • 用户注册访问
  • 用户登录
  • 用户注销

您可以在[这里](https://auth.bob-humphrey.com/) 进行尝试,并查看 [React客户端应用程序] 和 [Laravel服务器]的完整代码应用程序 (https://gitlab.com/Bob_Humphrey/react-auth)。.

关于 Laravel Sanctum

Laravel Sanctum 处理所有验证用户的工作。但是,有很多小细节可以设置这个设置。一次一个,不要错过任何步骤,您的应用程序将在非常短的时间内完美地工作。

本指南假设您对设置和运行 Laravel 应用程序(包括使用命令行和运行 Laravel artisan 命令)有基本的了解。

数据库

首先, 您需要一个数据库来保存您的信息. 我在此应用程序中使用了 Mysql,并创建了一个名为 auth 的数据库.

安装 Laravel

然后使用 Composer 创建 Laravel 应用程序:

composer create-project --prefer-dist laravel/laravel APP_NAME

在 [Laravel站点] 上有关于启动新项目的详细说明:(https://laravel.com/docs/7.x#installing-laravel).

编辑 .env 文件以更新应用程序名称和数据库信息。.

APP_NAME=Laravel_Sanctum_Authentication
APP_ENV=local
APP_KEY=base64:XXXXXXX
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=auth
DB_USERNAME=XXXXXXX
DB_PASSWORD=XXXXXXX

安装和配置 Sanctum

CD 安装并配置到应用程序目录中,并将 Sanctum 添加到项目中.

composer require laravel/sanctum

下一步,创建 Sanctum 配置文件和数据库表.

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

php artisan migrate

更新 app/Http/Kernel.php 以将 Sanctum 中间件添加到API中间件组。

添加以下行代码

use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

'api' => [
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

如下图所示 :

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

class Kernel extends HttpKernel
{
    /**
     * 应用程序的全局HTTP中间件堆栈.
     *
     * 这些中间件在对您的应用程序的每次请求期间运行.
     *
     * @var array
     */
    protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \Fruitcake\Cors\HandleCors::class,
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    /**
     * 应用程序的路由中间件组.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            EnsureFrontendRequestsAreStateful::class,
            'throttle:60,1',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

配置 CORS

我们需要设置 Cross-Origin Resource Sharing(跨域资源共享) 以便拒绝对我们API的请求,除非它们来自我们前端 React 应用程序.

对 config/cors.php 做以下更改.

'paths' => ['api/*', 'sanctum/csrf-cookie'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['https://auth.bob-humphrey.com', 'http://localhost:3000'],
    //'allowed_origins' => ['*'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => true,

修改 paths,以指示需要保护哪些端点: 在本例中为 api/ 和 sanctum/csrf-cookie.

'paths' => ['api/*', 'sanctum/csrf-cookie'],

修改 allowed-origins 以指定接受请求的URL. 这将是你的 React 应用程序的生产和开发url, https://auth.bob-humphrey.com (我的应用程序) and http://localhost:3000.

'allowed_origins' => ['https://auth.bob-humphrey.com', 'http://localhost:3000'],

然后将 support_credentials 设置为 true.

'supports_credentials' => true,

用户控制器(User controller)

接下来, 创建用户控制器.

php artisan make:controller UserController

编辑 app/Http/Controllers/UserController 使其成为这样.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use App\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class UserController extends Controller
{
    public function register(Request $request)
    {
        $this->validator($request->all())->validate();
        $user = $this->create($request->all());
        $this->guard()->login($user);
        return response()->json([
            'user' => $user,
            'message' => 'registration successful'
        ], 200);
    }
    /**
     * 为传入的注册请求获取验证器.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            //'password' => ['required', 'string', 'min:4', 'confirmed'],
            // NO PASSWORD CONFIRMATION
            'password' => ['required', 'string', 'min:4'],
        ]);
    }

    /**
     * 有效注册后创建新的用户实例.
     *
     * @param  array  $data
     * @return \App\User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }
    protected function guard()
    {
        return Auth::guard();
    }

    public function login(Request $request)
    {
        $credentials = $request->only('email', 'password');

        if (Auth::attempt($credentials)) {
            // Authentication passed...
            $authuser = auth()->user();
            return response()->json(['message' => 'Login successful'], 200);
        } else {
            return response()->json(['message' => 'Invalid email or password'], 401);
        }
    }

    public function logout()
    {
        Auth::logout();
        return response()->json(['message' => 'Logged Out'], 200);
    }
}

控制器包含前端将调用的寄存器(register)、登录(login)和注销(logout)方法。它还包含验证数据的验证程序方法和将新用户添加到数据库的创建方法.

API 路由

现在我们更新 routes/api 如下.

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Route::post('/login', 'UserController@login');
Route::post('/register', 'UserController@register');
Route::get('/logout', 'UserController@logout');

修改 /user 路由以使用我们刚刚安装的 Sanctum 中间件。除非用户首先通过身份验证,否则前端应用程序将无法从该终结点获取成功的响应。如果我们正在构建一个完整的API,那么所有 API 路由都将受到 Sanctum 中间件的保护.

我们还添加了三个新的端点,以提供对登录、注册和注销功能的访问。请注意,routes/api.php文件中的所有端点都将以 “/api” 作为前缀。因此,登录路由的端点是 “/api/login”,注册路由的端点是 “/api/register”,以此类推.

添加新用户进行测试

此时 Laravel 已完全设置为处理用户身份验证。让我们向数据库中添加一个新用户,以便测试我们的设置。我们可以使用 tinker 来完成这项工作.

php artisan tinker

factory(App\User::class)->create(['email'=>'bill@gmail.com','name'=>'Bill', 'password'=> bcrypt('bill')]);

exit     (to leave tinker)

第二部分

后端已经完成,我们现在可以构建前端了。在 第二部分 中,我们将介绍创建React应用程序所需的任务,以及用于用户注册、登录和注销的表单.

原文地址:https://dev.to/dog_smile_factory/authenticating-a-react-app-with-laravel-sanctum-part-1-44hl

译文地址:https://learnku.com/laravel/t/43674

关于极客返利

极客返利 是由我个人开发的一款网课返利、返现平台。包含 极客时间返现、拉勾教育返现、掘金小册返现、GitChat返现。目前仅包含这几个平台。后续如果有需要可以考虑其他平台。 简而言之就是:你买课,我返现。让你花更少的钱,就可以买到课程。

https://geek.laravelcode.cn

https://geek.idaka.ink

版权许可

本作品采用 知识共享署名 4.0 国际许可协议 进行许可。

转载无需与我联系,但须注明出处,注明文章来源 Laravel 7 + React.js 如何使用 Sanctum 做认证,第一部分