Webアプリケーションを開発するときは、通常、2つの層に分割することをお勧めします。中間層APIはデータベースと対話し、Web層は通常フロントエンドSPAまたはMPAで構成されます。このように、Webアプリケーションはより疎結合になり、長期的な管理とデバッグが容易になります。
APIが作成されている場合、ステートレスAPIコンテキストで認証と状態を設定することはやや問題があるように思われるかもしれません。
この記事では、LaravelとPassportを使用してAPIに完全なユーザー認証と簡単な形式のアクセス制御を実装する方法を見ていきます。での作業経験が必要です Laravel これは入門チュートリアルではないためです。
インストールの前提条件:
composer require laravel/helpers
上記をインストールしたら、開始する準備が整いました。 .env
を編集して、データベース接続を設定してください。ファイル。
まず、ダミーリクエスト用のコントローラーとモデルを作成します。このチュートリアルでは、このモデルはあまり役に立ちません。コントローラーが操作するデータの概念を示すためだけのものです。
モデルとコントローラーを作成する前に、移行を作成する必要があります。ターミナル内—またはcmd.exe
Windowsを使用している場合は、ウィンドウ-実行:
php artisan make:migration create_articles_table --create=articles
次に、database/migrations
に移動しますフォルダを開き、xxxx_xx_xx_xxxxxx_create_articles_table.php
のような名前でファイルを開きます。
up
でクラスの機能として、次のように記述します。
Schema::create('articles', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->string('body'); $table->integer('user_id'); $table->timestamps(); });
次に、Article
を作成しますモデル。これを行うには、次を実行します。
php artisan make:model Article
次に、ArticleController
を作成します実行することによるコントローラー:
php artisan make:controller ArticleController --resource
次に、ファイルを編集しますapp/Providers/AppServiceProvider.php
IlluminateSupportFacadesSchema
をインポートします追加することによるクラス:
use IlluminateSupportFacadesSchema
…ファイルの上部にあるインポートの下部に。
次に、boot
で関数、次のように記述します。
Schema::defaultStringLength(191);
これがすべて完了したら、次のコマンドを実行できます。
php artisan migrate
…上記で作成した移行を適用します。
ここでは、APIが機能するために必要なミドルウェアを追加します。
最初に必要なのはForceJsonResponse
ですミドルウェア。すべての応答をJSONに自動的に変換します。
これを行うには、次を実行します。
php artisan make:middleware ForceJsonResponse
そして、これはApp/Http/Middleware/ForceJsonReponse.php
にあるそのミドルウェアのハンドル機能です。
public function handle($request, Closure $next) { $request->headers->set('Accept', 'application/json'); return $next($request); }
次に、ミドルウェアをapp/Http/Kernel.php
に追加します$routeMiddleware
内のファイルアレイ:
'json.response' => AppHttpMiddlewareForceJsonResponse::class,
次に、それを$middleware
にも追加します同じファイル内の配列:
AppHttpMiddlewareForceJsonResponse::class,
これにより、ForceJsonResponse
が確実になりますミドルウェアはすべてのリクエストで実行されます。
私たちの消費者を許可するために Laravel REST API 別のオリジンからアクセスするには、CORSを設定する必要があります。そのために、Cors
というミドルウェアを作成します。
ターミナルまたはコマンドプロンプトで、cd
プロジェクトのルートディレクトリに移動して、次のコマンドを実行します。
php artisan make:middleware Cors
次に、app/Http/Middleware/Cors.php
に次のコードを追加します。
public function handle($request, Closure $next) { return $next($request) ->header('Access-Control-Allow-Origin', '*') ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') ->header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, X-Token-Auth, Authorization'); }
このミドルウェアをロードするには、app/Http/Kernel.php
の$routeMiddleware
に行を追加する必要がありますアレイ:
'cors' => AppHttpMiddlewareCors::class,
また、それを$middleware
に追加する必要があります以前のミドルウェアで行ったように配列:
AppHttpMiddlewareCors::class,
その後、このルートグループをroutes/api.php
に追加します。
Route::group(['middleware' => ['cors', 'json.response']], function () { // ... });
以下に示すように、すべてのAPIルートがその関数に入ります。
次に、login
を使用して認証コントローラーを作成します。およびregister
機能。
まず、以下を実行します。
php artisan make:controller Auth/ApiAuthController
次に、いくつかのクラスをファイルapp/Http/Controllers/Auth/ApiAuthController.php
にインポートします。これらのクラスは、login
の作成に使用されます。およびregister
機能。以下を追加してクラスをインポートします。
use AppUser; use IlluminateSupportFacadesHash; use IlluminateSupportFacadesValidator; use IlluminateSupportStr;
…コントローラーの上部に。
ここで、ユーザーにLaravel API認証を追加するために、login
、logout
、およびregister
を作成します。 (サインアップ)同じファイル内の関数。
register
関数は次のようになります。
public function register (Request $request) { $validator = Validator::make($request->all(), [ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:6|confirmed', ]); if ($validator->fails()) { return response(['errors'=>$validator->errors()->all()], 422); } $request['password']=Hash::make($request['password']); $request['remember_token'] = Str::random(10); $user = User::create($request->toArray()); $token = $user->createToken('Laravel Password Grant Client')->accessToken; $response = ['token' => $token]; return response($response, 200); }
login
関数は次のようになります:
public function login (Request $request) { $validator = Validator::make($request->all(), [ 'email' => 'required|string|email|max:255', 'password' => 'required|string|min:6|confirmed', ]); if ($validator->fails()) { return response(['errors'=>$validator->errors()->all()], 422); } $user = User::where('email', $request->email)->first(); if ($user) { if (Hash::check($request->password, $user->password)) { $token = $user->createToken('Laravel Password Grant Client')->accessToken; $response = ['token' => $token]; return response($response, 200); } else { $response = ['message' => 'Password mismatch']; return response($response, 422); } } else { $response = ['message' =>'User does not exist']; return response($response, 422); } }
そして最後に、logout
関数:
public function logout (Request $request) { $token = $request->user()->token(); $token->revoke(); $response = ['message' => 'You have been successfully logged out!']; return response($response, 200); }
この後、login
、register
、およびlogout
を追加する必要があります私たちのルートへの機能、すなわち、 ルートグループ内 すでにAPIにあります:
Route::group(['middleware' => ['cors', 'json.response']], function () { // ... // public routes Route::post('/login', 'Auth [email protected] ')->name('login.api'); Route::post('/register','Auth [email protected] ')->name('register.api'); Route::post('/logout', 'Auth [email protected] ')->name('logout.api'); // ... });
最後に、HasApiToken
を追加する必要がありますUser
への特性モデル。 app/User
に移動しますそして、あなたが持っていることを確認してください:
use HasApiTokens, Notifiable;
…クラスのトップに。
アプリケーションサーバーを起動した場合(つまり、php artisan serve
を実行した場合)、GET
を送信しようとします。ルート/api/user
にリクエストすると、次のメッセージが表示されます。
{ 'message': 'Unauthenticated.' }
これは、認証されていないためです そのルートにアクセスする 。選択したルートを保護するために、それらをroutes/api.php
に追加できます。 Route::post
の直後行:
Route::middleware('auth:api')->group(function () { // our routes to be protected will go in here });
先に進む前に、ログアウトルートをauth:api
に追加しますLaravelはトークンを使用してユーザーをログアウトするためのミドルウェア— auth:api
の外部からアクセスできないトークンミドルウェア。私たちの 公衆 ルートは次のようになります。
Route::group(['middleware' => ['cors', 'json.response']], function () { // ... // public routes Route::post('/login', 'Auth [email protected] ')->name('login.api'); Route::post('/register', 'Auth [email protected] ')->name('register.api'); // ... });
私たちの 保護 一方、ルートは次のようになります。
Route::middleware('auth:api')->group(function () { // our routes to be protected will go in here Route::post('/logout', 'Auth [email protected] ')->name('logout.api'); });
次に、ArticleController
に移動しますapp/Http/Controllers/ArticleController.php
で作成しましたcreate
を削除しますおよびedit
そのクラスのメソッド。その後、残りの各関数に、少し編集した次のコードを追加します。
$response = ['message' => ' function']; return response($response, 200);
必要に応じて記入します。たとえば、update
関数はこれを本体として持ちます:
$response = ['message' => 'update function']; return response($response, 200);
ユーザーを登録するために、POST
を送信します/api/register
へのリクエスト次のパラメーターを使用:name
、email
(一意である必要があります)、password
、およびpassword_confirmation
。
t9キーボードとは何ですか
ユーザーが作成されると、APIはトークンを返します。トークンは、認証の手段として以降のリクエストで使用されます。
ログインするには、POST
を送信します/api/login
へのリクエスト。資格情報が正しければ、この方法でLaravelログインAPIからトークンも取得します。
このリクエストから返される認証トークンは、保護されたルートにアクセスするときに使用できます。 Postmanでは、[認証]タブにドロップダウンがあり、タイプを[ベアラートークン]に設定できます。その後、トークンをトークンフィールドに入力できます。
プロセスは非常に似ています 不眠症 。
cURLユーザーは、パラメーター-H 'Authorization: Bearer '
を渡すことで同等のことを行うことができます。ここで、ログインまたは登録応答から与えられた認証トークンです。
cURLと同様に、開発者がaxiosまたはその種のライブラリを使用してAPIを使用することを計画している場合は、Authorization
を追加できます。値がBearer
のヘッダー。
基本認証が完了したので、次はパスワードリセット機能を設定します。
これを行うには、api_auth
を作成することを選択できますコントローラディレクトリ、新しいカスタムコントローラを作成し、関数を実装します。または、Laravelで生成できる認証コントローラーを編集することもできます。この場合、アプリケーション全体がAPIであるため、認証コントローラーを編集します。
まず、以下を実行して認証コントローラーを生成します。
composer require laravel/ui php artisan ui vue --auth
app/Http/Controllers/Auth/ForgotPasswordController.php
でクラスを編集し、次の2つのメソッドを追加します。
protected function sendResetLinkResponse(Request $request, $response) { $response = ['message' => 'Password reset email sent']; return response($response, 200); } protected function sendResetLinkFailedResponse(Request $request, $response) { $response = 'Email could not be sent to this email address'; return response($response, 500); }
次に、実際にパスワードをリセットするコントローラーを設定する必要があるため、app/Http/Controllers/Auth/ResetPasswordController.php
に移動します。次のようなデフォルトの関数をオーバーライドします。
protected function resetPassword($user, $password) { $user->password = Hash::make($password); $user->save(); event(new PasswordReset($user)); } protected function sendResetResponse(Request $request, $response) { $response = ['message' => 'Password reset successful']; return response($response, 200); } protected function sendResetFailedResponse(Request $request, $response) { $response = 'Token Invalid'; return response($response, 401); }
また、次を追加して、コントローラーにいくつかのクラスをインポートする必要があります。
use IlluminateAuthEventsPasswordReset; use IlluminateHttpRequest; use IlluminateSupportFacadesHash;
…コントローラーの上部に。
Laravelに付属するメール通知は承認にAPIトークンを使用しないため、使用するメール通知も変更する必要があります。 app/Notifications
の下に新しいものを作成できますこのコマンドを実行することにより:
php artisan make:notification MailResetPasswordNotification
ファイルを編集する必要がありますapp/Notifications/MailResetPasswordNotification.php
このように見えるように:
pageUrl = 'localhost:8080'; // we can set whatever we want here, or use .env to set environmental variables } /** * Get the notification's delivery channels. * * @param mixed $notifiable * @return array */ public function via($notifiable) { return ['mail']; } /** * Get the mail representation of the notification. * * @param mixed $notifiable * @return IlluminateNotificationsMessagesMailMessage */ public function toMail($notifiable) { if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $this->token); } return (new MailMessage) ->subject(Lang::getFromJson('Reset application Password')) ->line(Lang::getFromJson('You are receiving this email because we received a password reset request for your account.')) ->action(Lang::getFromJson('Reset Password'), $this->pageUrl.'?token='.$this->token) ->line(Lang::getFromJson('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.users.expire')])) ->line(Lang::getFromJson('If you did not request a password reset, no further action is required.')); } /** * Get the array representation of the notification. * * @param mixed $notifiable * @return array */ public function toArray($notifiable) { return [ // ]; } }
この新しい通知を利用するには、sendPasswordResetNotification
をオーバーライドする必要がありますUser
という方法Authenticatable
から継承しますクラス。これをapp/User.php
に追加するだけです。
public function sendPasswordResetNotification($token) { $this->notify(new AppNotificationsMailResetPasswordNotification($token)); }
メールの設定が適切に機能していれば、この時点で通知が機能しているはずです。
現在残っているのは、ユーザーアクセス制御だけです。
アクセス制御ミドルウェアを作成する前に、user
を更新する必要があります。 type
という名前の列を持つテーブル。これは、ユーザーレベルを決定するために使用されます。タイプ0は通常のユーザー、タイプ1は管理者、タイプ2はスーパー管理者です。
user
を更新するにはテーブルでは、これを実行して移行を作成する必要があります。
php artisan make:migration update_users_table_to_include_type --table=users
database/migrations/[timestamp]_update_users_table.php
の形式で新しく作成されたファイルで、up
を更新する必要がありますおよびdown
type
を追加および削除する関数それぞれ、列:
public function up() { Schema::table('users', function (Blueprint $table) { $table->integer('type'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('users', function (Blueprint $table) { $table->dropIfExists('type'); }); }
次に、php artisan migrate
を実行します。これが完了したら、register
を編集する必要がありますApiAuthController.php
の関数ファイル、$user = User::create($request->toArray());
の行の直前にこれを追加します。
$request['type'] = $request['type'] ? $request['type'] : 0;
また、この行を$validator
に追加する必要がありますアレイ:
'type' => 'integer',
これら2つの編集の最初のものは、デフォルトですべての登録ユーザーを「通常のユーザー」にします。つまり、ユーザータイプが入力されていない場合です。
これで、アクセス制御に使用する2つのミドルウェアを作成できるようになりました。1つは管理者用、もう1つはスーパー管理者用です。
実行します:
php artisan make:middleware AdminAuth php artisan make:middleware SuperAdminAuth
まず、app/Http/Middleware/AdminAuth.php
に移動しますIlluminateSupportFacadesAuth
をインポートしてから、handle
を編集しますそのように機能します:
public function handle($request, Closure $next) { if (Auth::guard('api')->check() && $request->user()->type >= 1) { return $next($request); } else { $message = ['message' => 'Permission Denied']; return response($message, 401); } }
handle
も編集する必要がありますapp/Http/Middleware/SuperAdminAuth.php
の関数:
public function handle($request, Closure $next) { if (Auth::guard('api')->check() && $request->user()->type >= 2) { return $next($request); } else { $message = ['message' => 'Permission Denied']; return response($message, 401); } }
Auth
もインポートする必要があります以下を追加して、両方のファイルの先頭にクラスを追加します。
use IlluminateSupportFacadesAuth;
…そこにある輸入品の一番下まで。
新しいミドルウェアを使用するために、app/Http/Kernel.php
に次の行を追加して、カーネル内、つまり$routeMiddleware
内の両方のクラスを参照します。アレイ:
'api.admin' => AppHttpMiddlewareAdminAuth::class, 'api.superAdmin' => AppHttpMiddlewareSuperAdminAuth::class,
開発者が特定のルートでミドルウェアを使用したい場合は、次のようにミドルウェアをルート関数に追加するだけです。
Route::post('route',' [email protected] ')->middleware('');
この場合、必要に応じてapi.admin
、api.superAdmin
などになります。
ミドルウェアを作成するために必要なのはこれだけです。
認証とアクセス制御が機能していることをテストするために、いくつかの追加手順を実行する必要があります。
ArticleController
のindex
を変更する必要があります機能し、ルートを登録します。 (実際のプロジェクトでは、PHPUnitを使用し、自動テストの一部としてこれを実行します。ここでは、テスト目的でルートを手動で追加しています。後で削除できます。)
ArticleController
に移動しますapp/Http/Controllers/ArticleController
のコントローラーindex
を変更しますこのように見える関数:
public function index() { $response = ['message' => 'article index']; return response($response, 200); }
次に、routes/api.php
に移動して、ルートに関数を登録します。ファイルとこれを追加します:
Route::middleware('auth:api')->group(function () { Route::get('/articles', ' [email protected] ')->name('articles'); });
これで、認証トークンなしでルートへのアクセスを試みることができます。認証エラーが発生するはずです。
また、認証トークン(この記事の前半で登録またはログインして取得したもの)を使用して同じルートにアクセスすることもできます。
これにより、次のようなエラーが発生する場合があります。
Unknown column 'api_token' in 'where clause' (SQL: select * from `users` where `api_token` = ...
これが発生した場合、開発者は 確認してください Passport移行を実行し、['guards']['api']['driver']
を持っているpassport
に設定config/auth.php
で:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ],
その後、構成キャッシュも更新する必要があります。
それが修正されると、ルートにアクセスできるようになります。
アクセス制御をテストする時が来ました。追加しましょう->middleware('api.admin')
記事のルートに移動するため、次のようになります。
Route::get('/articles', ' [email protected] ')->middleware('api.admin')->name('articles');
api/user
でわかるように、新しく作成されたユーザーには自動的にタイプ0が割り当てられるようにしました。ルート。
そのため、articles
にアクセスしようとするとエラーが発生するはずです。そのようなユーザーとしてのエンドポイント。
テストの目的で、データベース内のユーザーを変更してtype
を設定しましょう。 api/user
を介してその変更を確認した後もう一度ルートを設定して、GET
に再試行する準備ができました/articles/
ルート。
それは完璧に動作します。
より複雑なアプリケーションを作成している開発者は、適切なアクセス制御がこれほど単純ではないことに注意する必要があります。その場合、他のサードパーティアプリケーションまたはLaravelの ゲートとポリシー カスタムユーザーアクセス制御を実装するために使用できます。このシリーズの第2部では、より堅牢で柔軟なアクセス制御ソリューションについて説明します。
すべてのデバイスのブートストラップメディアクエリ
このLaravelPassportチュートリアルでは、以下について説明しました。
これらは、の分野で働く人にとって不可欠なスキルです Laravel開発サービス 。読者は最終結果を このGitHubリポジトリ これで、Laravelで認証を実装できるようになりました。以下のコメントをお待ちしております。
Laravel Passportは、Laravelを使用したAPI認証用のOAuth2.0サーバー実装です。トークンは一般的にAPI認証で使用されるため、Laravel Passportは、OAuth2.0サーバーにトークン認証を実装するための簡単で安全な方法を提供します。
Laravel Passportは、Laravel RESTAPIで認証を実装するために使用されるパッケージです。
Laravel Passportは、ステートレス認証用のOAuth2.0サーバー実装です。 OAuth 2.0は最新のOAuthプロトコルであり、安全です。
ステートレスAPIは、それに対する各リクエストが完全に分離されており、各リクエストの応答がリクエストのみに完全に依存しているAPIです。これは、各リクエストの応答がサーバーとリクエストの「状態」に依存するステートフルアプリケーションとは異なります。