Laravel 11 REST API Authentication认证使用Sanctum插件教程

在本教程中,我们将通过使用Sanctum应用程序开发完整的Laravel 11 REST API身份验证以及简单的分步指南来了解使用Sanctum身份验证的Laravel 11 REST API
我们将从头开始学习APIREST APILaravel Sanctum,并创建一个示例API

API是什么?

API(应用程序编程接口)只是两个或多个计算机程序之间的一种通信方式。
API还用于Web和移动应用程序开发;因此,构建REST API对于任何Web和移动应用程序开发人员来说都非常重要。

Laravel Sanctum是什么?

Laravel SanctumLaravel应用程序的API身份验证包,为单页应用程序(SPA)、移动应用程序和其他API驱动的项目提供轻量级、简单易用的身份验证系统。它使用JSON Web令牌(JWT) 或API令牌提供基于令牌的身份验证,从而实现安全身份验证,而无需传统基于会话的身份验证的开销。Sanctum简化了令牌身份验证的设置,使开发人员能够专注于构建他们的应用程序,而不是处理身份验证的复杂性。
我们将使用Laravel Sanctum,这是一个身份验证系统包,用于为SPA(单页应用程序)开发简单的API,这些API 通常通过React JSAngularVue JS构建。
在此示例中,我们将安装Laravel 11应用程序。然后,我们将安装用于API身份验证的Sanctum composer包。之后,我们将创建用于用户身份验证的注册和登录API。然后,我们将创建一个产品REST API,并且您必须使用用户令牌进行身份验证。因此,让我们按照以下步骤逐步完成此示例:

按照以下步骤在Laravel 11应用程序中创建RESTful API完整示例。

第一步 安装Laravel 11

如果已经安装可以忽略;如果您尚未创建Laravel应用程序,则可以继续执行以下命令:

composer create-project laravel/laravel example-app

第二步 安装组件Sanctum API

Laravel 11中,默认情况下,我们没有api.php路由文件。因此,您只需要运行以下命令即可安装带有api.php文件的Sanctum

php artisan install:api

第三步 配制Sanctum文件

在此步骤中,我们必须配置三个位置:模型、服务提供商和身份验证配置文件。因此,您只需要在这些文件中进行以下更改:
在模型中,我们添加了SanctumHasApiTokens类。
auth.php中,我们添加了API身份验证配置。

app/Models/User.php

<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
  
class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
  
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];
  
    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];
  
    /**
     * Get the attributes that should be cast.
     *
     * @return array
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}

第四步 添加Product TableProduct模型

接下来,我们需要使用laravel artisan命令为products表创建迁移。因此,首先,执行以下命令:

php artisan make:migration create_products_table

执行此命令后,您将在以下路径database/migrations中找到一个文件,并且您必须将以下代码放入迁移文件中才能创建products表。

<?php
    
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
    
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('detail');
            $table->timestamps();
        });
    }
    
    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};

创建迁移后,我们需要通过以下命令运行上述迁移:

php artisan migrate

创建Product表后,应为产品创建产品模型。因此,首先,在此路径app/Models/Product.php创建一个文件,并将以下内容放入item.php文件中:

app/Models/Product.php

<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
  
class Product extends Model
{
    use HasFactory;
  
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'detail'
    ];
}

第五步创建API路由

在此步骤中,我们将为loginregisterroducts REST API创建API路由。因此,让我们在该文件中添加一个新路由。

routes/api.php

<?php
  
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
   
Route::controller(App\Http\Controllers\Api\RegisterController::class)->group(function(){
    Route::post('register', 'register');
    Route::post('login', 'login');
});

Route::middleware('auth:sanctum')->group( function () {
    Route::resource('products', App\Http\Controllers\Api\ProductController::class);
});

第六步创建控制器Controller文件

在下一步中,我们创建了一个名为ControllerProductControllerRegisterController的新控制器。我在Controllers文件夹中创建了一个名为API的新文件夹,因为我们将有单独的API控制器。因此,让我们创建两个控制器。

app/Http/Controllers/Api/Controller.php

<?php
  
namespace App\Http\Controllers\Api;
  
use Illuminate\Http\Request;
  
class Controller
{
    /**
     * success response method.
     *
     * @return \Illuminate\Http\Response
     */
    public function sendResponse($result, $message)
    {
        $response = [
            'status'  => 1,
            'data'    => $result,
            'message' => $message,
        ];
  
        return response()->json($response, 200);
    }
  
    /**
     * return error response.
     *
     * @return \Illuminate\Http\Response
     */
    public function sendError($error, $errorMessages = [], $code = 404)
    {
        $response = [
            'status' => 1,
            'message' => $error,
        ];
  
        if(!empty($errorMessages)){
            $response['data'] = $errorMessages;
        }
  
        return response()->json($response, $code);
    }
}

app/Http/Controllers/Api/RegisterController.php

<?php
   
namespace App\Http\Controllers\Api;

use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Validator;
   
class RegisterController extends Controller
{
    /**
     * Register api
     *
     * @return \Illuminate\Http\Response
     */
    public function register(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'email' => 'required|email',
            'password' => 'required',
            'c_password' => 'required|same:password',
        ]);
   
        if($validator->fails()){
            return $this->sendError('Validation Error.', $validator->errors());       
        }
   
        $input = $request->all();
        $input['password'] = bcrypt($input['password']);
        $user = User::create($input);
        $success['token'] =  $user->createToken('MyApp')->plainTextToken;
        $success['name'] =  $user->name;
   
        return $this->sendResponse($success, 'User register successfully.');
    }
   
    /**
     * Login api
     *
     * @return \Illuminate\Http\Response
     */
    public function login(Request $request): JsonResponse
    {
        if(Auth::attempt(['email' => $request->email, 'password' => $request->password])){ 
            $user = Auth::user(); 
            $success['token'] =  $user->createToken('MyApp')->plainTextToken; 
            $success['name'] =  $user->name;
   
            return $this->sendResponse($success, 'User login successfully.');
        } 
        else{ 
            return $this->sendError('Unauthorised.', ['error'=>'Unauthorised']);
        } 
    }
}

app/Http/Controllers/Api/ProductController.php

<?php
   
namespace App\Http\Controllers\Api;

use App\Http\Resources\ProductResource;
use App\Models\Product;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Validator;
   
class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(): JsonResponse
    {
        $products = Product::all();
    
        return $this->sendResponse(ProductResource::collection($products), 'Products retrieved successfully.');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request): JsonResponse
    {
        $input = $request->all();
   
        $validator = Validator::make($input, [
            'name' => 'required',
            'detail' => 'required'
        ]);
   
        if($validator->fails()){
            return $this->sendError('Validation Error.', $validator->errors());       
        }
   
        $product = Product::create($input);
   
        return $this->sendResponse(new ProductResource($product), 'Product created successfully.');
    } 
   
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id): JsonResponse
    {
        $product = Product::find($id);
  
        if (is_null($product)) {
            return $this->sendError('Product not found.');
        }
   
        return $this->sendResponse(new ProductResource($product), 'Product retrieved successfully.');
    }
    
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Product $product): JsonResponse
    {
        $input = $request->all();
   
        $validator = Validator::make($input, [
            'name' => 'required',
            'detail' => 'required'
        ]);
   
        if($validator->fails()){
            return $this->sendError('Validation Error.', $validator->errors());       
        }
   
        $product->name = $input['name'];
        $product->detail = $input['detail'];
        $product->save();
   
        return $this->sendResponse(new ProductResource($product), 'Product updated successfully.');
    }
   
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Product $product): JsonResponse
    {
        $product->delete();
   
        return $this->sendResponse([], 'Product deleted successfully.');
    }
}

第七步 创建Eloquent API Resources资源

这是在Laravel 11中创建REST API的一个非常重要的步骤。您可以将Eloquent API资源与API一起使用。它将帮助您保持模型对象的相同响应布局。我们在ProductController文件中使用了它。现在,我们必须使用以下命令创建它:

php artisan make:resource ProductResource

现在,已创建一个新文件,其中包含以下路径中的新文件夹:

app/Http/Resources/ProductResource.php

<?php
  
namespace App\Http\Resources;
  
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
  
class ProductResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @return array
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'detail' => $this->detail,
            'created_at' => $this->created_at->format('d/m/Y'),
            'updated_at' => $this->updated_at->format('d/m/Y'),
        ];
    }
}

第八步 为了API结果统一,把异常进行改造如下:

<?php

use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
    })
    ->withExceptions(function (Exceptions $exceptions) {
        // 以下可据实际做相应调整
        $exceptions->render(function(AuthenticationException|RouteNotFoundException|HttpException|ErrorException $exception, Request $request) {

            if ($request->is('api/*')) {

                $statusCode = match (true) {
                    $exception instanceof RouteNotFoundException  => 404,
                    $exception instanceof AuthenticationException => 401,
                    default => 200
                };

                $status = match (true) {
                    500 > $statusCode && $statusCode > 400  => 4,
                    default => 1
                };

                return response()->json(
                    [
                        'status'    => $status,
                        'message'   => $exception->getMessage()
                    ],
                    $statusCode
                );
            }
        });
    })->create();

所有必需的步骤都已完成。现在,您必须键入以下给定的命令并按回车键以运行Laravel应用程序:

php artisan serve

现在,转到您的Postman并检查以下API

请确保在详细信息API中,我们将使用如下所示的请求头信息,登陆和注册除外:

'headers' => [
    'Accept' => 'application/json',
    'Authorization' => 'Bearer '.$accessToken,
]

实例效果

以下是运行实例截图。

Register API: 请求方式:GETURL地址: http://localhost:8000/api/register

Login API: 请求方式:GETURL地址: http://localhost:8000/api/login

Product List API: 请求方式: GETURL地址: http://localhost:8000/api/products

Product Create API: 请求方式: POSTURL地址: http://localhost:8000/api/products

Product Show API: 请求方式: GETURL地址: http://localhost:8000/api/products/{id}

Product Update API: 请求方式: PUTURL地址: http://localhost:8000/api/products/{id}

Product Delete API: 请求方式: DELETEURL地址: http://localhost:8000/api/products/{id}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值