web-dev-qa-db-ja.com

Laravelパスポートで401未認証エラーが発生する

LaravelパスポートをAPI認証に使用しています。1つのDBで使用すると完全に機能しますが、複数のデータベースを使用すると_401_が得られます。

私がやっていること:

  • 私はマルチテナントDBを持っており、マスターDBにはユーザー、ロール、そしてすべてのOAuthテーブルがあります。
  • 管理者の役割を持つユーザーを作成すると、管理者の名前で新しいDBが作成され、ユーザー、役割、およびすべてのサブデータベースが作成されますOAuthテーブル。サブDBの_oauth_clients_がコピーされますマスターDBからのパスワード付与トークンとパーソナルアクセストークン、およびサブDBへの挿入、および_client_id_への_oauth_personal_access_clients_の挿入。
  • _passport:install_コマンドが実行するすべての手順を実行しています。 (私が何かを逃していない場合)。

  • マスターDBからの資格情報でログインすると完全に機能します。実際の問題は、サブデータベースから資格情報でログインしたときに始まります。emailで入力したパラメーター_client_code_からサブDBを取得できます。ログイン中のpassword.

  • サブDBからログインできますが、ログイン中に_401 Unauthenticated_エラーが発生し、アクセストークンを取得します。AuthenticationヘッダーにBearerを付けてAngularを渡します_ フロント。

  • ここで何が欠けているのか分からない。

DBConnectionミドルウェア

DBConnectionミドルウェアは、ログイン後にすべてのリクエストで接続を設定します。

_public function handle($request, Closure $next)
    {
        if ( $request->method() != 'OPTIONS' ) {            
            $this->access_code = $request->header('access-code'); 
            if ( $this->access_code != '' && $this->access_code != 'sa'  ) {
                app('App\Http\Controllers\Controller')->setDB(AppHelper::DB_PREFIX.$this->access_code);
            } else {
                app('App\Http\Controllers\Controller')->setDB(AppHelper::DB_DEFAULT);
            }
        }
        return $next($request);
    }
_

DBConnectionはデフォルトのDBを_database.php_に動的に設定します。そのため、__($ OME] _で作成されたsetDBメソッドを呼び出します_Controller.php_

setDB Controller.php

_public function setDB($database='') {
      $config = app()->make('config');
      $connections = $config->get('database.connections');
      $default_connection = $connections[$config->get('database.default')];
      $new_connection = $default_connection;
      $new_connection['database'] = $database;
      $config->set('database.connections.'.$database, $new_connection);
      $config->set('database.default', $database);
  }
_

同じコードに対して2つの異なるDBでpassportを使用することは可能ですか?

_Laravel 5.4_フロントエンドに_Passport 4.0_ _Angular 4.4_

29
Nikhil Radadiya

あなたの質問に答えるには:はい、できます!

ミドルウェアでは、次のようにしています。

config([
  'database.connections.tenant.schema' => $tenant
]);

DB::connection('tenant')->statement("SET search_path = $tenant");

Search_pathが正しく設定されていないように思えます。これは、401を取得する理由を説明します。 Laravel Passportが間違ったデータベースを検索しているため、ユーザーテーブルで適切なトークンを見つけることができないためです。

PostgreSQL docs( https://www.postgresql.org/docs/9.1/static/runtime-config-client.html )から:

search_path(文字列)

この変数は、スキーマが指定されていない単純な名前でオブジェクト(テーブル、データ型、関数など)が参照される場合に、スキーマが検索される順序を指定します。異なるスキーマに同じ名前のオブジェクトがある場合、検索パスで最初に見つかったオブジェクトが使用されます。検索パス内のどのスキーマにも含まれていないオブジェクトは、その含まれているスキーマを修飾(ドット付き)名で指定することによってのみ参照できます。

1
tprj29

これはCORSの問題です。 OPTIONSリクエストは、Authorizationヘッダーを配信しません。

オリジンがホストと異なる場合、ブラウザは他のリクエストの前にOPTIONSを送信します。

CORSミドルウェアがセットアップされていない場合、Laravelはステータス401で応答します。

したがって、RESTfulアーキテクチャでは、クライアントアプリのホストがAPIのホストと異なる場合、CORSミドルウェアを使用する必要があります。

これを使用できます: barryvdh/laravel-cors

$ composer require barryvdh/laravel-cors

例:

App\Http\Kernel.php

protected $routeMiddleware = [
    ...
    'auth.cors' => \Barryvdh\Cors\HandleCors::class,
    ...
];

web.php

Route::group([
    'prefix' => 'api',
    'middleware' => [
        'auth.cors'
    ]
], function () {
    Route::post('user/authenticate', 'UserController@authenticate');
});

CORSミドルウェアが適切に機能する場合、ブラウザはOPTIONSリクエストでステータス200を受け取り、ペイロードを使用して最初のリクエストを起動します。

0
Emma Paulowicz