ホームページ > 記事 > PHPフレームワーク > Laravel を使用して JWT 認証を統合し、RestfulApi を開発する
この記事では、JWT 認証を使用して Laravel で RESTful API を構築する方法を学びます。 JWT は JSON Web トークンの略です。また、API を使用して、ユーザー製品用の完全に機能する CRUD アプリケーションを作成します。
API は、クロスプラットフォーム アプリケーションを使用する場合に非常に良い選択肢です。 Web サイトに加えて、製品には Android および iOS アプリも含まれている場合があります。この場合、バックエンド コードを変更せずにさまざまなフロントエンドを作成できるため、API も同様に優れています。 API を使用する場合、いくつかのパラメーターを指定して GET、POST、またはその他のタイプのリクエストを実行するだけで、サーバーは JSON (JavaScript Object Notation) 形式でデータを返し、クライアント アプリケーションによって処理されます。
手順
まずは、アプリケーションの詳細と機能を書き留めましょう。 JWT認証を使用したlaravelのRestful APIを使用して、基本的なユーザー製品リストを構築します。
A ユーザー は次の機能を使用します
登録して新しいアカウントを作成します
ログアカウントに移動します
ログアウトしてトークンを破棄し、アプリを終了します
ユーザー 必須
製品 必須
##数量
これにより、jwt という名前のディレクトリに新しい Laravel プロジェクトが作成されます。
JWT 拡張パッケージの構成
Laravel で JWT を使用できるようにするために、tymondesigns/jwt-auth 拡張パッケージを使用します。
tymon/jwt-auth 拡張パッケージをインストールします
この拡張パッケージをこの Laravel アプリケーションにインストールしましょう。 Laravel 5.5 以降を使用している場合は、次のコマンドを実行して JWT パッケージの開発-開発バージョンを取得してください: composer require tymon/jwt-auth:dev-develop --prefer-source
Laravel 5.4 以前を使用している場合は、次のコマンドを実行します:
composer require tymon/jwt-auth
Laravel バージョン 5.5 より前のアプリケーションの場合は、config/app.php ファイルでサービスプロバイダーとエイリアスを設定する必要もあります。
'providers' => [ .... Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class, .... ], 'aliases' => [ .... 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory', .... ],
Laravel のバージョンが 5.5 以降の場合、Laravel は「パッケージの自動検出」を実行します。
設定ファイルの公開
Laravel バージョン 5.5 以降の場合は、次のコマンドを使用して設定ファイルを公開してください: php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
Laravel の以前のバージョンの場合は、次のコマンドを実行する必要があります:
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
上記のコマンドは config/jwt.php 構成ファイルを生成します。コメントがなければ、構成ファイルは次のようになります。
<?php return [ 'secret' => env('JWT_SECRET'), 'keys' => [ 'public' => env('JWT_PUBLIC_KEY'), 'private' => env('JWT_PRIVATE_KEY'), 'passphrase' => env('JWT_PASSPHRASE'), ], 'ttl' => env('JWT_TTL', 60), 'refresh_ttl' => env('JWT_REFRESH_TTL', 20160), 'algo' => env('JWT_ALGO', 'HS256'), 'required_claims' => [ 'iss', 'iat', 'exp', 'nbf', 'sub', 'jti', ], 'persistent_claims' => [ // 'foo', // 'bar', ], 'lock_subject' => true, 'leeway' => env('JWT_LEEWAY', 0), 'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true), 'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0), 'decrypt_cookies' => false, 'providers' => [ 'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class, 'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class, 'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class, ], ];
JWT キーの生成
JWT トークンは、暗号化されたキーを使用して発行されます。 Laravel 5.5 以降の場合、次のコマンドを実行してトークンを発行するためのキーを生成します。 php artisan jwt:secret
Laravel バージョンが 5.5 より前の場合は、次を実行します:
php artisan jwt:generate
このチュートリアルでは Laravel 5.6 を使用します。チュートリアルの次の手順は、5.5 と 5.6 でのみテストされています。 Laravel 5.4 以前では動作しない可能性があります。 Laravel の古いバージョンのドキュメントを読むことができます。
登録ミドルウェア
JWT 認証拡張パッケージには、それを使用できるようにするミドルウェアが付属しています。 auth.jwt ミドルウェアを app/Http/Kernel.php に登録します: protected $routeMiddleware = [
....
'auth.jwt' => \Tymon\JWTAuth\Http\Middleware\Authenticate::class,
];
このミドルウェアは、リクエストに添付されたトークンをチェックすることでユーザーの認証を検証します。ユーザーが認証されていない場合、このミドルウェアは UnauthorizedHttpException 例外をスローします。
ルーティングのセットアップ
始める前に、このチュートリアルで説明するすべてのポイントのルーティングをセットアップします。 Routes/api.php を開き、次のルートをファイルにコピーします。 Route::post('login', 'ApiController@login');
Route::post('register', 'ApiController@register');
Route::group(['middleware' => 'auth.jwt'], function () {
Route::get('logout', 'ApiController@logout');
Route::get('user', 'ApiController@getAuthUser');
Route::get('products', 'ProductController@index');
Route::get('products/{id}', 'ProductController@show');
Route::post('products', 'ProductController@store');
Route::put('products/{id}', 'ProductController@update');
Route::delete('products/{id}', 'ProductController@destroy');
});
ユーザー モデルの更新
JWT は、ユーザー モデルに Tymon\JWTAuth\Contracts\JWTSubject インターフェイスを実装する必要があります。このインターフェイスは、getJWTIdentifier と getJWTCustomClaims の 2 つのメソッドを実装する必要があります。 app/User.php を次の内容で更新します。 <?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 = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* 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 [];
}
}
JWT 認証ロジック
JWT 認証を使用して、laravel で Restful API のロジックを書いてみましょう。 用户注册时需要姓名,邮箱和密码。那么,让我们创建一个表单请求来验证数据。通过运行以下命令创建名为 RegisterAuthRequest 的表单请求: 它将在 app/Http/Requests 目录下创建 RegisterAuthRequest.php 文件。将下面的代码黏贴至该文件中。 运行以下命令创建一个新的 ApiController : 这将会在 app/Http/Controllers 目录下创建 ApiController.php 文件。将下面的代码黏贴至该文件中。 让我解释下上面的代码发生了什么。 在 register 方法中,我们接收了 RegisterAuthRequest 。使用请求中的数据创建用户。如果 loginAfterSignUp 属性为 true ,则注册后通过调用 login 方法为用户登录。否则,成功的响应则将伴随用户数据一起返回。 在 login 方法中,我们得到了请求的子集,其中只包含电子邮件和密码。以输入的值作为参数调用 JWTAuth::attempt() ,响应保存在一个变量中。如果从 attempt 方法中返回 false ,则返回一个失败响应。否则,将返回一个成功的响应。 在 logout 方法中,验证请求是否包含令牌验证。通过调用 invalidate 方法使令牌无效,并返回一个成功的响应。如果捕获到 JWTException 异常,则返回一个失败的响应。 在 getAuthUser 方法中,验证请求是否包含令牌字段。然后调用 authenticate 方法,该方法返回经过身份验证的用户。最后,返回带有用户的响应。 身份验证部分现在已经完成。 构建产品部分 要创建产品部分,我们需要 Product 模型,控制器和迁移文件。运行以下命令来创建 Product 模型,控制器和迁移文件。 它会在 database/migrations 目录下创建一个新的数据库迁移文件 create_products_table.php,更改 up 方法。 向 Product 模型中添加 fillable 属性。在 app 目录下打开 Product.php 文件并添加属性。 现在在 .env 文件中设置数据库凭证,并通过运行以下命令迁移数据库。 现在,我们必须在 User 模型中添加一个关系来检索相关产品。在 app/User.php 中添加以下方法。 在 app/Http/Controllers 目录下打开 ProductController.php 文件。在文件开头添加 use 指令覆盖上一个。 现在我们将实现五个方法。 index, 为经过身份认证的用户获取所有产品列表 show, 根据 ID 获取特定的产品 store, 将新产品存储到产品列表中 update, 根据 ID 更新产品详情 destroy, 根据 ID 从列表中删除产品 添加一个构造函数来获取经过身份认证的用户,并将其保存在 user 属性中。 parseToken 将解析来自请求的令牌, authenticate 通过令牌对用户进行身份验证。 让我们添加 index 方法。 上面的代码非常简单,我们只是使用 Eloquent 的方法获取所有的产品,然后将结果组成一个数组。最后,我们返回这个数组。Laravel 将自动将其转换为 JSON ,并创建一个为 200 成功的响应码。 继续实现 show 方法。 这个也非常容易理解。我们只需要根据 ID 找到该产品。如果产品不存在,则返回 400 故障响应。否则,将返回产品数组。 接下来是 store 方法 在 store 方法中,验证请求中是否包含名称,价格和数量。然后,使用请求中的数据去创建一个新的产品模型。如果,产品成功的写入数据库,会返回成功响应,否则返回自定义的 500 失败响应。 实现 update 方法 在 update 方法中,我们通过 id 取得产品。如果产品不存在,返回一个 400 响应。然后,我们把请求中的数据使用 fill 方法填充到产品详情。更新产品模型并保存到数据库,如果记录成功更新,返回一个 200 成功响应,否则返回 500 内部服务器错误响应给客户端。 现在,让我们实现 destroy 方法。 在 destroy 方法中,我们根据 ID 获取产品,如果产品不存在,则返回 400 响应。然后我们删除产品后并根据删除操作的成功状态返回适当的响应。 控制器代码现在已经完成,完整的控制器代码在这。 测试 我们首先来测试身份认证。我们将使用 serve 命令在开发机上启动 Web 服务,你也可以使用虚拟主机代替。运行以下命令启动 Web 服务。 它将监听 localhost:8000 为了测试 restful API's,我们使用 Postman。填写好请求体之后,我们请求一下 register 路由。 リクエストを送信すると、トークンを取得します。 ユーザーは登録され、認証されました。ログイン ルートを検出するために別のリクエストを送信すると、200 とトークンが返されます。 Laravel チュートリアル 」php artisan make:request RegisterAuthRequest
<?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 [
'name' => 'required|string',
'email' => 'required|email|unique:users',
'password' => 'required|string|min:6|max:10'
];
}
}
php artisan make:controller ApiController
<?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([
'success' => true,
'data' => $user
], 200);
}
public function login(Request $request)
{
$input = $request->only('email', 'password');
$jwt_token = null;
if (!$jwt_token = JWTAuth::attempt($input)) {
return response()->json([
'success' => false,
'message' => 'Invalid Email or Password',
], 401);
}
return response()->json([
'success' => true,
'token' => $jwt_token,
]);
}
public function logout(Request $request)
{
$this->validate($request, [
'token' => 'required'
]);
try {
JWTAuth::invalidate($request->token);
return response()->json([
'success' => true,
'message' => 'User logged out successfully'
]);
} catch (JWTException $exception) {
return response()->json([
'success' => false,
'message' => 'Sorry, the user cannot be logged out'
], 500);
}
}
public function getAuthUser(Request $request)
{
$this->validate($request, [
'token' => 'required'
]);
$user = JWTAuth::authenticate($request->token);
return response()->json(['user' => $user]);
}
}
php artisan make:model Product -mc
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->string('name');
$table->integer('price');
$table->integer('quantity');
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
});
}
protected $fillable = [
'name', 'price', 'quantity'
];
php artisan migrate
public function products()
{
return $this->hasMany(Product::class);
}
use App\Product;
use Illuminate\Http\Request;
use JWTAuth;
protected $user;
public function __construct()
{
$this->user = JWTAuth::parseToken()->authenticate();
}
public function index()
{
return $this->user
->products()
->get(['name', 'price', 'quantity'])
->toArray();
}
public function show($id)
{
$product = $this->user->products()->find($id);
if (!$product) {
return response()->json([
'success' => false,
'message' => 'Sorry, product with id ' . $id . ' cannot be found'
], 400);
}
return $product;
}
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required',
'price' => 'required|integer',
'quantity' => 'required|integer'
]);
$product = new Product();
$product->name = $request->name;
$product->price = $request->price;
$product->quantity = $request->quantity;
if ($this->user->products()->save($product))
return response()->json([
'success' => true,
'product' => $product
]);
else
return response()->json([
'success' => false,
'message' => 'Sorry, product could not be added'
], 500);
}
public function update(Request $request, $id)
{
$product = $this->user->products()->find($id);
if (!$product) {
return response()->json([
'success' => false,
'message' => 'Sorry, product with id ' . $id . ' cannot be found'
], 400);
}
$updated = $product->fill($request->all())
->save();
if ($updated) {
return response()->json([
'success' => true
]);
} else {
return response()->json([
'success' => false,
'message' => 'Sorry, product could not be updated'
], 500);
}
}
public function destroy($id)
{
$product = $this->user->products()->find($id);
if (!$product) {
return response()->json([
'success' => false,
'message' => 'Sorry, product with id ' . $id . ' cannot be found'
], 400);
}
if ($product->delete()) {
return response()->json([
'success' => true
]);
} else {
return response()->json([
'success' => false,
'message' => 'Product could not be deleted'
], 500);
}
}
php artisan serve
以上がLaravel を使用して JWT 認証を統合し、RestfulApi を開発するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。