Laravel护照给401未经验证的错误 [英] Laravel passport gives 401 Unauthenticated error

查看:478
本文介绍了Laravel护照给401未经验证的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我在做什么:

  • 我有一个多租户数据库,主数据库有用户,角色和所有OAuth表.
  • 当我创建一个具有管理员角色的用户时,它将创建一个具有管理员名称的新数据库,它将创建一个具有用户,角色和所有OAuth表的子数据库.子数据库的oauth_clients将从主数据库复制密码授予令牌和个人访问令牌,然后插入子数据库,并在oauth_personal_access_clients中插入client_id.
  • 我正在执行passport:install命令所执行的所有过程. (如果我没有丢失任何东西).

  • 当我使用主数据库中的凭据登录时,它可以正常运行,当我使用子数据库中的凭据登录时,真正的问题就开始了,我可以从用email输入的参数client_code中获取子DB. ,password登录时.

  • 它允许我从子数据库登录,但出现401 Unauthenticated错误,登录时获取Access令牌,并且从Angular前端登录后,在每次请求时都将Authentication标头和Bearer传递给. p>

  • 不知道我在这里想念什么.

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动态设置database.php中的默认数据库,为此,我正在调用在Controller.php上创建的setDB方法

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);
  }

是否可以将passport与2个不同的DB用作同一代码?

Laravel 5.4 Passport 4.0 Angular 4.4在前端

解决方案

这是CORS问题. OPTIONS请求未提供授权标头.

如果来源不同于主机,则浏览器将在其他任何请求之前发送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,并使用有效负载触发初始请求.

I'm using Laravel passport for API authentication, it works perfectly when I use it with one DB, but gives 401 when using multiple databases,

What I'm doing:

  • I have a multi-tenant DB, master DB have users, roles and all OAuth tables.
  • When I create a user with admin role it will create new DB with admin name, it will create sub DB with users, roles and all OAuth table. oauth_clients of sub DB will copy Password Grant Token and Personal Access Token from master DB and insert in sub DB, and also insert client_id in oauth_personal_access_clients.
  • I'm doing all the procedures which passport:install command does. (If I'm not missing something).

  • When I login with credentials from master DB it works perfectly, the real problem starts when I login with credentials from sub-database, I can get sub DB from a param client_code which I input with email,password while login.

  • It allows me login from sub DB but I get 401 Unauthenticated error, get Access token while login and I pass Authentication Header with Bearer on every request after login from Angular front.

  • Don't know what I'm missing here.

DBConnection Middleware

DBConnection middleware sets connection on every request after login,

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 sets default DB in database.php dynamically, for that, I'm calling setDB method created on 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);
  }

Is it possible to use passport with 2 different DB for same code?

Laravel 5.4 Passport 4.0 Angular 4.4 in front-end

解决方案

This is CORS issue. OPTIONS request does not deliver Authorization headers.

If the origin is different from the host, browser going to send OPTIONS before any other request.

Laravel going to answer with the status 401 if CORS middleware is not set up.

So with RESTful architecture, if the client app host is different from the API's host you have to use CORS middleware.

You may use this one: barryvdh/laravel-cors

$ composer require barryvdh/laravel-cors

Example:

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');
});

If CORS middleware works properly a browser shall receive status 200 on the OPTIONS request and fire the initial request with a payload.

这篇关于Laravel护照给401未经验证的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆