乐趣区

使用-Laravel-Passport-为你的-REST-API-增加用户认证功能

在本教程中,我们将了解如何在 Laravel 应用中使用 laravel passport 认证。我们还将使用 Laravel Passport 认证 构建一个简单的产品(创建,查询,更新和删除)。

Laravel 已经提供了传统的登录表单身份验证,但是如果你想使用 APIs 呢?APIs 使用令牌来验证用户,因为它们不使用会话。当用户通过 API 登录时,会生成令牌并将其发送给用户,该用户可用于身份验证。Laravel 提供 Passport,可以毫无困难地使用 API 认证。

让我们看看如何在 Laravel 应用程序中设置和配置用于 API 认证和 RESTful APIs 的 Laravel Passport。

创建一个新的应用

我们新建一个 Laravel 应用。执行下面的命令就可以创建一个全新的laravel 应用。

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

安装 Passport 扩展

我们使用 composer 安装 Passport 扩展。执行下面的命令来安装这个扩展。

composer require laravel/passport

Laravel配置Passport

Laravel Passport 扩展需要做一些配置。

服务提供者

我们使用的 Laravel 5.6 最新版本,它可以使用包发现并自动注册服务。如果你使用 laravel 5.4 或者 更低版本 ,你需要在 config/app.php 文件中为Passport 注册服务。就这样,在这个文件中的 providers 数组中添加注册服务。

'providers' => [
    ....
    Laravel\Passport\PassportServiceProvider::class,
]

迁移和安装

.env 文件中设置数据库凭据。Laravel Passport 提供了需要在我们的数据库中的护照表的迁移文件。Passport 迁移用于存储令牌和客户端信息。运行migration 命令以将架构迁移到数据库。

php artisan migrate

接下来,需要使用以下命令安装 Passport。它将生成生成秘密访问令牌所需的加密密钥。

php artisan passport:install

Passport 配置

在此步骤中,我们需要在 Laravel 应用程序中进行更改以完成 Passport 配置。

app/User.php

在你的  User model 中添加 LaravelPassportHasApiTokens trait。它将提供一些辅助方法。

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

    /**
     * 这是可被赋值属性集合
     *
     * @var array
     */
    protected $fillable = ['name', 'email', 'password',];

    /**
     * 这是应该被隐藏的属性集合
     *
     * @var array
     */
    protected $hidden = ['password', 'remember_token',];
}

AuthServiceProvider

AuthServiceProvider 的引导方法中添加 Passport :: routes() 方法。它将生成必要的路由。这是 app/Providers/AuthServiceProvider.php 在更改后的样子。

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = ['App\Model' => 'App\Policies\ModelPolicy',];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {$this->registerPolicies();

        Passport::routes();}
}

config/auth.php

在 config/auth.php 文件中,将驱动程序设置为 passport。

return [
    ....

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
    ],

    ....
]

创建路由

让我们创建 API 路由,在 routes/api.php 添加路由。

Route::post('login', 'PassportController@login');
Route::post('register', 'PassportController@register');

Route::middleware('auth:api')->group(function () {Route::get('user', 'PassportController@details');

    Route::resource('products', 'ProductController');
});

创建认证控制器

让我们设置身份验证逻辑。通过运行以下命令创建 Passport 控制器。

php artisan make:controller PassportController

将以下代码复制到 app/Http/Controllers/PassportController.php

<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;

class PassportController extends Controller
{
    /**
     * Handles Registration Request
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function register(Request $request)
    {
        $this->validate($request, [
            'name' => 'required|min:3',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:6',
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password)
        ]);

        $token = $user->createToken('TutsForWeb')->accessToken;

        return response()->json(['token' => $token], 200);
    }

    /**
     * Handles Login Request
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {
        $credentials = [
            'email' => $request->email,
            'password' => $request->password
        ];

        if (auth()->attempt($credentials)) {$token = auth()->user()->createToken('TutsForWeb')->accessToken;
            return response()->json(['token' => $token], 200);
        } else {return response()->json(['error' => 'UnAuthorised'], 401);
        }
    }

    /**
     * Returns Authenticated User Details
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function details()
    {return response()->json(['user' => auth()->user()], 200);
    }
}

让我来解释一下上面的代码

在 register 的方法中,我们验证请求数据然后创建用户。我们使用  createToken 方法创建 token,并将名称作为参数传递。最后,我们在 JSON 响应中返回 token。

在  login 方法中,我们尝试使用请求参数进行身份验证。然后,根据尝试的成功或失败返回适当的响应。

在 details 方法中我们只返回用户模型。

创建产品 CRUD

让我们创建一个产品的 CRUD。运行以下命令生成产品模型、迁移文件、和控制器。

php artisan make:model Product -mc

它将创建一个新的数据库迁移文件 create_products_table.php 在 database/migrations 文件夹.
将 up 方法更新成以下代码。

public function up()
{Schema::create('products', function (Blueprint $table) {$table->increments('id');
        $table->integer('user_id');
        $table->string('name');
        $table->integer('price');
        $table->timestamps();

        $table->foreign('user_id')
            ->references('id')
            ->on('users');
    });
}

现在, 添加 fillable 属性到 Product 模型. 打开 app 文件夹下的 Product.php 文件.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = ['name', 'price'];
}

现在我们运行数据迁移。

php artisan migrate

现在,让我们在 app/User.php 文件中添加关联关系方法。

public function products()
{return $this->hasMany(Product::class);
}

打开 app/Http/Controllers 文件夹中的 ProductController.php 文件。复制以下代码到到产品控制器。

<?php

namespace App\Http\Controllers;

use App\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{public function index()
    {$products = auth()->user()->products;

        return response()->json([
            'success' => true,
            'data' => $products
        ]);
    }

    public function show($id)
    {$product = auth()->user()->products()->find($id);

        if (!$product) {return response()->json([
                'success' => false,
                'message' => 'Product with id' . $id . 'not found'
            ], 400);
        }

        return response()->json([
            'success' => true,
            'data' => $product->toArray()], 400);
    }

    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required',
            'price' => 'required|integer'
        ]);

        $product = new Product();
        $product->name = $request->name;
        $product->price = $request->price;

        if (auth()->user()->products()->save($product))
            return response()->json([
                'success' => true,
                'data' => $product->toArray()]);
        else
            return response()->json([
                'success' => false,
                'message' => 'Product could not be added'
            ], 500);
    }

    public function update(Request $request, $id)
    {$product = auth()->user()->products()->find($id);

        if (!$product) {return response()->json([
                'success' => false,
                'message' => 'Product with id' . $id . 'not found'
            ], 400);
        }

        $updated = $product->fill($request->all())->save();

        if ($updated)
            return response()->json(['success' => true]);
        else
            return response()->json([
                'success' => false,
                'message' => 'Product could not be updated'
            ], 500);
    }

    public function destroy($id)
    {$product = auth()->user()->products()->find($id);

        if (!$product) {return response()->json([
                'success' => false,
                'message' => 'Product with id' . $id . 'not found'
            ], 400);
        }

        if ($product->delete()) {return response()->json(['success' => true]);
        } else {return response()->json([
                'success' => false,
                'message' => 'Product could not be deleted'
            ], 500);
        }
    }
}

测试

现在,我们的逻辑已经完成,让我们开始测试。我们将在 PHP 开发服务器上测试它,但你可以根据需要使用虚拟主机。运行以下命令以在 PHP 开发服务器上提供应用程序。

php artisan serve

现在让我们用测试工具测试我们的 API Postman.

注册接口

登陆接口

详情接口

在测试详情接口或需要用户进行身份验证的任何 API 时,你需要指定两个标头请求头信息。你必须在 Authorization 请求头中将 token 指定为 Bearer token。基本上,你必须将登录和注册后收到的 token 拼到 Bearer 后面,当中空一个空格。

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

产品列表接口

产品添加接口

产品展示接口

产品更新接口

产品删除接口

本教程的完整代码可以从 github 获取 GitHub

文章转自:https://learnku.com/laravel/t…

更多文章:https://learnku.com/laravel/c…

退出移动版