Maison  >  Article  >  cadre php  >  Utiliser Laravel pour intégrer l'authentification JWT pour développer RestfulApi

Utiliser Laravel pour intégrer l'authentification JWT pour développer RestfulApi

Guanhui
Guanhuiavant
2020-05-09 10:43:452431parcourir

Dans cet article, nous apprendrons comment créer une API reposante dans Laravel en utilisant l'authentification JWT. JWT signifie JSON Web Tokens. Nous utiliserons également l'API pour créer une application CRUD entièrement fonctionnelle pour le produit utilisateur.

L'API est un très bon choix lors de l'utilisation d'applications multiplateformes. En plus d'un site Web, votre produit peut également disposer d'applications Android et iOS. Dans ce cas, l'API est tout aussi intéressante car vous pouvez écrire différentes interfaces sans modifier le code backend. Lorsque vous utilisez l'API, appuyez simplement sur GET , POST ou tout autre type de requête avec certains paramètres, et le serveur renverra certaines données au format JSON (JavaScript Object Notation), qui sont traitées par l'application client.

Instructions

Commençons par noter les détails et les fonctionnalités de notre application. Nous allons créer une liste de produits utilisateur de base à l'aide de l'API restful dans Laravel en utilisant l'authentification JWT.

Un utilisateur utilisera les fonctionnalités suivantes

  • S'inscrire et créer un nouveau compte

  • Connexion Accédez à leur compte

  • Déconnectez-vous, supprimez le jeton et quittez l'application

  • Obtenez les détails de l'utilisateur connecté

  • Récupérer une liste de produits disponibles pour l'utilisateur

  • Rechercher un produit spécifique par ID

  • Ajouter un nouveau produit au produit de l'utilisateur liste

  • Modifier les détails du produit existant

  • Supprimer le produit existant de la liste des utilisateurs

A Utilisateur Obligatoire

  • nom

  • e-mail

  • mot de passe

Un Produit Obligatoire

  • nom

  • prix

  • quantité

Créer un nouvel article

En exécutant la commande suivante, nous pouvons démarrer et créer un nouveau projet Laravel.

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

Cela créera un nouveau projet Laravel dans un répertoire appelé jwt.

Configuration du package d'extension JWT

Nous utiliserons le package d'extension tymondesigns/jwt-auth pour nous permettre d'utiliser JWT dans Laravel.

Installez le package d'extension tymon/jwt-auth

Installons ce package d'extension dans cette application Laravel. Si vous utilisez Laravel 5.5 ou une version ultérieure, veuillez exécuter la commande suivante pour obtenir la version dev-develop du package JWT :

composer require tymon/jwt-auth:dev-develop --prefer-source

Si vous utilisez Laravel 5.4 ou une version antérieure, exécutez la commande suivante :

composer require tymon/jwt-auth

Pour les applications avec des versions de Laravel inférieures à 5.5, vous devez également définir le fournisseur de services et l'alias dans le fichier config/app.php.

'providers' => [
    ....
    Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
    ....
],
'aliases' => [
    ....
    'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
    'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
    ....
],

Si votre version de Laravel est 5.5 ou supérieure, Laravel effectuera une "découverte automatique des packages".

Publier le fichier de configuration

Pour Laravel version 5.5 ou supérieure, veuillez utiliser la commande suivante pour publier le fichier de configuration :

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

Pour les versions précédentes de Laravel, vous devez exécuter la commande suivante :

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"

La commande ci-dessus générera le fichier de configuration config/jwt.php. Sans les commentaires, le fichier de configuration ressemblerait à ceci :

<?php
return [
    &#39;secret&#39; => env(&#39;JWT_SECRET&#39;),
    &#39;keys&#39; => [
        &#39;public&#39; => env(&#39;JWT_PUBLIC_KEY&#39;),
        &#39;private&#39; => env(&#39;JWT_PRIVATE_KEY&#39;),
        &#39;passphrase&#39; => env(&#39;JWT_PASSPHRASE&#39;),
    ],
    &#39;ttl&#39; => env(&#39;JWT_TTL&#39;, 60),
    &#39;refresh_ttl&#39; => env(&#39;JWT_REFRESH_TTL&#39;, 20160),
    &#39;algo&#39; => env(&#39;JWT_ALGO&#39;, &#39;HS256&#39;),
    &#39;required_claims&#39; => [
        &#39;iss&#39;,
        &#39;iat&#39;,
        &#39;exp&#39;,
        &#39;nbf&#39;,
        &#39;sub&#39;,
        &#39;jti&#39;,
    ],
    &#39;persistent_claims&#39; => [
        // &#39;foo&#39;,
        // &#39;bar&#39;,
    ],
    &#39;lock_subject&#39; => true,
    &#39;leeway&#39; => env(&#39;JWT_LEEWAY&#39;, 0),
    &#39;blacklist_enabled&#39; => env(&#39;JWT_BLACKLIST_ENABLED&#39;, true),
    &#39;blacklist_grace_period&#39; => env(&#39;JWT_BLACKLIST_GRACE_PERIOD&#39;, 0),
    &#39;decrypt_cookies&#39; => false,
    &#39;providers&#39; => [
        &#39;jwt&#39; => Tymon\JWTAuth\Providers\JWT\Lcobucci::class,
        &#39;auth&#39; => Tymon\JWTAuth\Providers\Auth\Illuminate::class,
        &#39;storage&#39; => Tymon\JWTAuth\Providers\Storage\Illuminate::class,
    ],
];

Générer la clé JWT

Les jetons JWT sont émis à l'aide d'une clé cryptée. Pour Laravel 5.5 ou supérieur, exécutez la commande suivante pour générer une clé permettant d'émettre des jetons.

php artisan jwt:secret

Les versions de Laravel inférieures à 5.5 s'exécutent :

php artisan jwt:generate

Ce tutoriel utilise Laravel 5.6. Les étapes suivantes du didacticiel n'ont été testées qu'en 5.5 et 5.6. Peut ne pas fonctionner avec Laravel 5.4 ou version antérieure. Vous pouvez lire la documentation des anciennes versions de Laravel.

Middleware d'enregistrement

L'extension d'authentification JWT est livrée avec un middleware qui nous permet de l'utiliser. Enregistrez le middleware auth.jwt dans app/Http/Kernel.php :

protected $routeMiddleware = [
    ....
    &#39;auth.jwt&#39; => \Tymon\JWTAuth\Http\Middleware\Authenticate::class,
];

Ce middleware vérifiera l'authentification de l'utilisateur en vérifiant le jeton attaché à la requête. Si l'utilisateur n'est pas authentifié, ce middleware lèvera une exception UnauthorizedHttpException.

Configurer le routage

Avant de commencer, nous allons configurer le routage pour tous les points abordés dans ce tutoriel. Ouvrez routes/api.php et copiez les routes suivantes dans votre fichier.

Route::post(&#39;login&#39;, &#39;ApiController@login&#39;);
Route::post(&#39;register&#39;, &#39;ApiController@register&#39;);
Route::group([&#39;middleware&#39; => &#39;auth.jwt&#39;], function () {
    Route::get(&#39;logout&#39;, &#39;ApiController@logout&#39;);
    Route::get(&#39;user&#39;, &#39;ApiController@getAuthUser&#39;);
    Route::get(&#39;products&#39;, &#39;ProductController@index&#39;);
    Route::get(&#39;products/{id}&#39;, &#39;ProductController@show&#39;);
    Route::post(&#39;products&#39;, &#39;ProductController@store&#39;);
    Route::put(&#39;products/{id}&#39;, &#39;ProductController@update&#39;);
    Route::delete(&#39;products/{id}&#39;, &#39;ProductController@destroy&#39;);
});

Mettre à jour le modèle utilisateur

JWT doit implémenter l'interface TymonJWTAuthContractsJWTSubject dans le modèle utilisateur. Cette interface doit implémenter deux méthodes getJWTIdentifier et getJWTCustomClaims. Mettez à jour app/User.php avec le contenu suivant.

<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
    use Notifiable;
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        &#39;name&#39;, &#39;email&#39;, &#39;password&#39;,
    ];
    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        &#39;password&#39;, &#39;remember_token&#39;,
    ];
    /**
     * Get the identifier that will be stored in the subject claim of the JWT.
     *
     * @return mixed
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }
    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
}

Logique d'authentification JWT

Écrivons la logique de l'API Restful dans Laravel en utilisant l'authentification JWT.

用户注册时需要姓名,邮箱和密码。那么,让我们创建一个表单请求来验证数据。通过运行以下命令创建名为 RegisterAuthRequest 的表单请求:

php artisan make:request RegisterAuthRequest

它将在 app/Http/Requests 目录下创建 RegisterAuthRequest.php 文件。将下面的代码黏贴至该文件中。

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RegisterAuthRequest extends FormRequest
{
    /**
     * 确定是否授权用户发出此请求
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }
    /**
     * 获取应用于请求的验证规则
     *
     * @return array
     */
    public function rules()
    {
        return [
            &#39;name&#39; => &#39;required|string&#39;,
            &#39;email&#39; => &#39;required|email|unique:users&#39;,
            &#39;password&#39; => &#39;required|string|min:6|max:10&#39;
        ];
    }
}

运行以下命令创建一个新的 ApiController :

php artisan make:controller ApiController

这将会在 app/Http/Controllers 目录下创建 ApiController.php 文件。将下面的代码黏贴至该文件中。

<?php
namespace App\Http\Controllers;
use App\Http\Requests\RegisterAuthRequest;
use App\User;
use Illuminate\Http\Request;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
class ApiController extends Controller
{
    public $loginAfterSignUp = true;
    public function register(RegisterAuthRequest $request)
    {
        $user = new User();
        $user->name = $request->name;
        $user->email = $request->email;
        $user->password = bcrypt($request->password);
        $user->save();
        if ($this->loginAfterSignUp) {
            return $this->login($request);
        }
        return response()->json([
            &#39;success&#39; => true,
            &#39;data&#39; => $user
        ], 200);
    }
    public function login(Request $request)
    {
        $input = $request->only(&#39;email&#39;, &#39;password&#39;);
        $jwt_token = null;
        if (!$jwt_token = JWTAuth::attempt($input)) {
            return response()->json([
                &#39;success&#39; => false,
                &#39;message&#39; => &#39;Invalid Email or Password&#39;,
            ], 401);
        }
        return response()->json([
            &#39;success&#39; => true,
            &#39;token&#39; => $jwt_token,
        ]);
    }
    public function logout(Request $request)
    {
        $this->validate($request, [
            &#39;token&#39; => &#39;required&#39;
        ]);
        try {
            JWTAuth::invalidate($request->token);
            return response()->json([
                &#39;success&#39; => true,
                &#39;message&#39; => &#39;User logged out successfully&#39;
            ]);
        } catch (JWTException $exception) {
            return response()->json([
                &#39;success&#39; => false,
                &#39;message&#39; => &#39;Sorry, the user cannot be logged out&#39;
            ], 500);
        }
    }
    public function getAuthUser(Request $request)
    {
        $this->validate($request, [
            &#39;token&#39; => &#39;required&#39;
        ]);
        $user = JWTAuth::authenticate($request->token);
        return response()->json([&#39;user&#39; => $user]);
    }
}

让我解释下上面的代码发生了什么。

在 register 方法中,我们接收了 RegisterAuthRequest 。使用请求中的数据创建用户。如果 loginAfterSignUp 属性为 true ,则注册后通过调用 login 方法为用户登录。否则,成功的响应则将伴随用户数据一起返回。

在 login 方法中,我们得到了请求的子集,其中只包含电子邮件和密码。以输入的值作为参数调用  JWTAuth::attempt() ,响应保存在一个变量中。如果从 attempt 方法中返回 false ,则返回一个失败响应。否则,将返回一个成功的响应。

在 logout 方法中,验证请求是否包含令牌验证。通过调用 invalidate 方法使令牌无效,并返回一个成功的响应。如果捕获到 JWTException 异常,则返回一个失败的响应。

在 getAuthUser 方法中,验证请求是否包含令牌字段。然后调用 authenticate 方法,该方法返回经过身份验证的用户。最后,返回带有用户的响应。

身份验证部分现在已经完成。

构建产品部分

要创建产品部分,我们需要 Product 模型,控制器和迁移文件。运行以下命令来创建 Product 模型,控制器和迁移文件。

php artisan make:model Product -mc

它会在 database/migrations 目录下创建一个新的数据库迁移文件 create_products_table.php,更改 up 方法。

public function up()
{
    Schema::create(&#39;products&#39;, function (Blueprint $table) {
        $table->increments(&#39;id&#39;);
        $table->integer(&#39;user_id&#39;);
        $table->string(&#39;name&#39;);
        $table->integer(&#39;price&#39;);
        $table->integer(&#39;quantity&#39;);
        $table->timestamps();
        $table->foreign(&#39;user_id&#39;)
            ->references(&#39;id&#39;)
            ->on(&#39;users&#39;)
            ->onDelete(&#39;cascade&#39;);
    });
}

向 Product 模型中添加 fillable 属性。在 app 目录下打开 Product.php 文件并添加属性。

protected $fillable = [
    &#39;name&#39;, &#39;price&#39;, &#39;quantity&#39;
];

现在在 .env 文件中设置数据库凭证,并通过运行以下命令迁移数据库。

php artisan migrate

现在,我们必须在 User 模型中添加一个关系来检索相关产品。在 app/User.php 中添加以下方法。

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

在 app/Http/Controllers 目录下打开 ProductController.php 文件。在文件开头添加 use 指令覆盖上一个。

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

现在我们将实现五个方法。

index, 为经过身份认证的用户获取所有产品列表

show, 根据 ID 获取特定的产品

store, 将新产品存储到产品列表中

update, 根据 ID 更新产品详情

destroy, 根据 ID 从列表中删除产品

添加一个构造函数来获取经过身份认证的用户,并将其保存在 user 属性中。

protected $user;
public function __construct()
{
    $this->user = JWTAuth::parseToken()->authenticate();
}

parseToken 将解析来自请求的令牌, authenticate 通过令牌对用户进行身份验证。

让我们添加 index 方法。

public function index()
{
    return $this->user
        ->products()
        ->get([&#39;name&#39;, &#39;price&#39;, &#39;quantity&#39;])
        ->toArray();
}

上面的代码非常简单,我们只是使用 Eloquent 的方法获取所有的产品,然后将结果组成一个数组。最后,我们返回这个数组。Laravel 将自动将其转换为 JSON ,并创建一个为 200 成功的响应码。

继续实现 show 方法。

public function show($id)
{
    $product = $this->user->products()->find($id);
    if (!$product) {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product with id &#39; . $id . &#39; cannot be found&#39;
        ], 400);
    }
    return $product;
}

这个也非常容易理解。我们只需要根据 ID 找到该产品。如果产品不存在,则返回 400 故障响应。否则,将返回产品数组。

接下来是 store 方法

public function store(Request $request)
{
    $this->validate($request, [
        &#39;name&#39; => &#39;required&#39;,
        &#39;price&#39; => &#39;required|integer&#39;,
        &#39;quantity&#39; => &#39;required|integer&#39;
    ]);
    $product = new Product();
    $product->name = $request->name;
    $product->price = $request->price;
    $product->quantity = $request->quantity;
    if ($this->user->products()->save($product))
        return response()->json([
            &#39;success&#39; => true,
            &#39;product&#39; => $product
        ]);
    else
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product could not be added&#39;
        ], 500);
}

在 store 方法中,验证请求中是否包含名称,价格和数量。然后,使用请求中的数据去创建一个新的产品模型。如果,产品成功的写入数据库,会返回成功响应,否则返回自定义的 500 失败响应。

实现 update 方法

public function update(Request $request, $id)
{
    $product = $this->user->products()->find($id);
    if (!$product) {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product with id &#39; . $id . &#39; cannot be found&#39;
        ], 400);
    }
    $updated = $product->fill($request->all())
        ->save();
    if ($updated) {
        return response()->json([
            &#39;success&#39; => true
        ]);
    } else {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product could not be updated&#39;
        ], 500);
    }
}

在 update 方法中,我们通过 id 取得产品。如果产品不存在,返回一个 400 响应。然后,我们把请求中的数据使用 fill 方法填充到产品详情。更新产品模型并保存到数据库,如果记录成功更新,返回一个 200 成功响应,否则返回 500 内部服务器错误响应给客户端。

现在,让我们实现 destroy 方法。

public function destroy($id)
{
    $product = $this->user->products()->find($id);
    if (!$product) {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Sorry, product with id &#39; . $id . &#39; cannot be found&#39;
        ], 400);
    }
    if ($product->delete()) {
        return response()->json([
            &#39;success&#39; => true
        ]);
    } else {
        return response()->json([
            &#39;success&#39; => false,
            &#39;message&#39; => &#39;Product could not be deleted&#39;
        ], 500);
    }
}

在 destroy 方法中,我们根据 ID 获取产品,如果产品不存在,则返回 400 响应。然后我们删除产品后并根据删除操作的成功状态返回适当的响应。

控制器代码现在已经完成,完整的控制器代码在这。

测试

我们首先来测试身份认证。我们将使用 serve 命令在开发机上启动 Web 服务,你也可以使用虚拟主机代替。运行以下命令启动 Web 服务。

php artisan serve

它将监听 localhost:8000

为了测试 restful API's,我们使用 Postman。填写好请求体之后,我们请求一下 register 路由。

Utiliser Laravel pour intégrer lauthentification JWT pour développer RestfulApi

Envoyez une demande et vous recevrez un jeton.

Utiliser Laravel pour intégrer lauthentification JWT pour développer RestfulApi

Notre utilisateur est désormais enregistré et authentifié. Nous pouvons envoyer une autre requête pour détecter la route de connexion, qui renverra un 200 et un jeton.

Utiliser Laravel pour intégrer lauthentification JWT pour développer RestfulApi

Obtenir les détails de l'utilisateur

Utiliser Laravel pour intégrer lauthentification JWT pour développer RestfulApi

Test d'authentification d'identité terminé. Ensuite, testez la partie produit, créez d’abord un produit.

Utiliser Laravel pour intégrer lauthentification JWT pour développer RestfulApi

Maintenant, récupérez le produit en demandant la méthode d'indexation.

Utiliser Laravel pour intégrer lauthentification JWT pour développer RestfulApi

Vous pouvez tester d'autres itinéraires et ils fonctionneront tous correctement.

Tutoriel recommandé : "Tutoriel Laravel"

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer