【问题标题】:Laravel dingo/api - Using internal routes with Passport (L6)Laravel dingo/api - 通过 Passport 使用内部路由(L6)
【发布时间】:2020-03-16 02:42:24
【问题描述】:

我看到很多人有类似的问题,但没有最终解决的解决方案。我一直在努力让它工作大约 24 小时,但仍然没有运气!

目标

  1. 使用 Laravel 6 和 Dingo API 构建和 API
  2. 能够在外部使用 API,通过 Passport oAuth 进行身份验证。
  3. 能够在内部通过 ajax 使用护照自验证功能使用 API。
  4. 能够通过 PHP 使用 dingo 的自消费方法在内部使用 API。

到目前为止我发现了什么

身份验证提供者顺序

我见过的大多数解决方案都建议同时设置护照身份验证和 dingo。这是auth:api(护照)和api.auth(野狗)。

// API route middleware
$api->group(['middleware' =>  'auth:api', 'api.auth'], function (Router $api) {
...

这里的api.auth 实际上是在 laravel 中设置的自定义身份验证提供程序,并配置为 dingo,它将护照逻辑桥接到 dingo。

// Auth provider
class DingoPassportAuthProvider extends Authorization
{
    protected $guard;

    public function __construct(AuthManager $auth)
    {
        dump('DingoPassportAuthProvider Instantiated');
        $this->guard = $auth->guard('api');
    }

    public function authenticate(Request $request, Route $route)
    {
        if ($this->guard->check()) {
            return $this->guard->user();
        }

        throw new UnauthorizedHttpException('Not authenticated via Passport.');
    }

    public function getAuthorizationMethod()
    {
        return 'Bearer';
    }
}
// Configured in dingo (Api.php)
'auth' => [
    'passport' => \App\Providers\DingoPassportAuthProvider::class,
],

如果我们将 dingo API 提供程序放在中间件堆栈的首位,我们会得到:

  • 如果您使用 be() 方法为调用指定用户,则内部 API 请求有效:$this->api->be($request->user())->get('/api/profile')

  • 外部 API 请求和内部 AJAX 请求正确验证,并且用户从自定义 dingo 身份验证提供程序返回,但是,由于某种原因,您无法从 API 控制器中访问此用户:$user = $request->user(); // null

如果我们将 Passport API 提供程序放在中间件堆栈的首位,我们会得到:

  • 内部 API 请求根本不起作用(总是返回 401)

  • 外部 API 请求和内部 AJAX 请求按预期工作。

  • 不再调用 dingo 护照提供程序上的 authenticate 方法。我认为这可能与内部调用返回的 401 有关。

我认为正确的方法是将护照身份验证放在首位。这样,我们在调用 dingo 身份验证之前对用户进行身份验证,导致两件事:

  1. Passport 按预期在本地运行。

  2. Dingo 内部 API 调用现在应该只能使用 $this->api->get('/api/profile') 调用(省略使用 be() 定义用户),但这不起作用。

目前我有以前的配置。 Passport 在外部和 ajax 调用中正常工作,但内部 dingo 调用总是返回 401。

我检查了一些样板模板,它们似乎没有什么不同。我想知道 L6 中是否发生了一些变化来解释为什么内部请求不起作用。

【问题讨论】:

    标签: php laravel authentication laravel-passport dingo-api


    【解决方案1】:

    我现在找到了一种解决方法,它可以解决大部分问题......

    在自定义 dingo 身份验证提供程序中:

    class DingoPassportAuthProvider extends Authorization
    {
        public function authenticate(Request $request, Route $route)
        {
            if (Auth::guard('web')->check()) {
                return Auth::guard('web')->user();
            }
    
            if (Auth::guard('api')->check()) {
                $user = Auth::guard('api')->user();
                Passport::actingAs($user);
    
                return $user;
            }
    
            throw new UnauthorizedHttpException('Not authenticated via Passport.');
        }
    
        public function getAuthorizationMethod()
        {
            return 'Bearer';
        }
    }
    

    现在检查请求是来自 web 警卫(内部请求)还是 api 警卫(外部或 ajax 请求)并返回正确的用户。

    对于 api 守卫,似乎存在用户经过身份验证但在控制器中实际上不可用的问题。为了解决这个问题,我添加了Passport::actingAs($user)。这可能不是最佳做法,但警卫现在正在按照他们应该的方式行事,并且在我的所有不同情况下都是如此。

    那么在API路由中间件中,我们只指定自定义的dingo provider。

    // API route middleware
    $api->group(['middleware' => 'api.auth'], function (Router $api) {
    ...
    

    需要注意的一点是,dingos be() 方法并没有像预期的那样工作。相反,您需要像在一般 laravel 应用中一样切换用户。

    \Auth::loginUsingId(2);
    $user = $this->api->get('/api/profile');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-26
      • 1970-01-01
      • 2020-01-06
      • 2017-02-13
      • 2018-04-19
      • 2018-09-21
      • 2019-10-24
      • 2017-10-18
      相关资源
      最近更新 更多