拉拉维尔护照显示401未经认证的错误search_path(字符串)

2022-08-30 15:21:40

我正在使用Laravel护照进行API身份验证,当我将其与一个数据库一起使用时,它可以完美地工作,但在使用多个数据库时会给出,401

我在做什么:

  • 我有一个多租户数据库,主数据库有用户,角色和所有OAuth表。
  • 当我创建具有管理员角色的用户时,它将使用管理员名称创建新数据库,它将创建具有用户,角色和所有OAuth表的子数据库。 的子 DB 将从主 DB 复制密码授予令牌和个人访问令牌并插入子 DB,并插入 到 .oauth_clientsclient_idoauth_personal_access_clients
  • 我正在做命令所做的所有过程。(如果我没有错过什么)。passport:install

  • 当我使用master DB的凭据登录时,它工作完美,真正的问题始于我使用子数据库的凭据登录时,我可以在登录时从我输入的参数中获取子数据库。client_codeemailpassword

  • 它允许我从子数据库登录,但我得到错误,在登录时获取访问令牌,并且在从前面登录后,我在每个请求上传递标头。401 UnauthenticatedAuthenticationBearerAngular

  • 不知道我在这里错过了什么。

数据库连接中间件

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.phpsetDBController.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个不同的数据库一起使用?passport

Laravel 5.4 Passport 4.0 Angular 4.4在前端


答案 1

回答您的问题:是的,您可以!

在我们的中间件中,我们做了一些这样的操作:

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(字符串)

此变量指定当对象(表、数据类型、函数等)由未指定架构的简单名称引用时搜索架构的顺序。当不同架构中存在名称相同的对象时,将使用在搜索路径中首先找到的对象。不在搜索路径中任何架构中的对象只能通过使用限定(点)名称指定其包含架构来引用。


答案 2

这是 CORS 问题。选项请求不传递授权标头。

如果源与主机不同,浏览器将在任何其他请求之前发送 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,
    ...
];

网.php

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

如果 CORS 中间件工作正常,浏览器应在 OPTIONS 请求上接收状态 200,并使用有效负载触发初始请求。


推荐