使用 Laravel Lumen + Passport 获取经过身份验证的用户时出现问题

Posted

技术标签:

【中文标题】使用 Laravel Lumen + Passport 获取经过身份验证的用户时出现问题【英文标题】:Problem getting authenticated user with Laravel Lumen + Passport 【发布时间】:2019-07-22 10:43:55 【问题描述】:

我正在使用 LumenPassport (https://github.com/dusterio/lumen-passport),并按照此处列出的一些教程进行操作。

我结合使用这些教程以及大量的 google 和 *** 搜索来实现我目前所拥有的:http://esbenp.github.io/2017/03/19/modern-rest-api-laravel-part-4/http://esbenp.github.io/2015/05/26/lumen-web-api-oauth-2-authentication/https://blog.pusher.com/make-an-oauth2-server-using-laravel-passport/

我目前取得的成就 1. 使用密码授权获取访问和刷新令牌 2. 将这些令牌存储在安全的仅 http cookie 3. 在 Lumen 的 AuthServiceProvider 中检索这些令牌

我不能做什么 1.通过AccessToken获取认证用户

我正在尝试访问以下任一端点:

$router->group(['middleware' => 'auth:api'], function () use ($router) 
    $router->get('/', function () use ($router) return $router->app->version(););
    $router->post('/logout', '\App\Auth\LoginController@logout');
);

我会立即得到一个未经授权的错误。经过一些深入研究,错误来自我知道在 AuthServiceProvider 之后调用的 Authenticate.php。我查看了 AuthServiceProvider 并根据 Lumen 的文档,这就是引导方法的样子。当然它使用的是“api”驱动程序,我必须将其切换到“passport”才能工作。

AuthServiceProvider.php

public function boot()

    $this->app['auth']->viaRequest('passport', function ($request) 
         // dd("test") // this works
         // dd(Auth::user());
         // dd($request->user());
         // dd(Auth::guard('api')->user());
    );

Authenticate.php

public function handle($request, Closure $next, $guard = null)

    if ($this->auth->guard($guard)->guest()) 
        $status = Response::HTTP_UNAUTHORIZED;
        return response()->json(['success' => false, 'status' => $status, 'message' => 'HTTP_UNAUTHORIZED'], $status);
    
    return $next($request);

从这里,我仍然无法获得任何经过身份验证的用户信息。我已确保使用 Postman 使用适当的 Authorization 标头访问这些端点。

我需要检索用户的原因是因为我希望在我的注销方法中,我将能够检索该经过身份验证的用户的 accessToken 并撤销令牌并清除 cookie。

LoginController.php

public function logout()
    
        // Get the accessToken from Auth
        // Need to fix AuthServiceProvider first
        $accessToken = $this->auth->user()->token();
        $refreshToken = $this->db
            ->table('oauth_refresh_tokens')
            ->where('access_token_id', $accessToken->id)
            ->update([
                'revoked' => true,
            ]);

        $accessToken->revoke();

        $this->cookie->queue($this->cookie->forget(self::REFRESH_TOKEN));
    

【问题讨论】:

我看到你错过了AuthServiceProvider 的回复,我想你已经尝试过了?它应该返回 null 或 User @SvenHakvoort 嗨,斯文,对不起,我不知道为什么,但我的评论不知何故被删除了。无论如何,我已经尝试过了。在 Lumen 文档中,它声明了以下代码 $this->app['auth']->viaRequest('api', function ($request) // Return User or null... ); 我知道我们必须在这里返回一个用户,但我的问题是我无法从我在标头中发送的不记名访问令牌中检索用户。我尝试了不同的方法,即 dd('test') 下面的 3 行,它们都以套接字挂断错误作为响应。 你的 boostrap/app.php 中有 $app->configure('auth'); 吗? @SvenHakvoort 是的,我愿意!如果我在 AuthServiceProvider.php@boot 中手动返回用户,我可以验证 Auth 在 LoginController.php@logout 中是否正常工作......但是,即使我这样做,我也无法通过调用 $this->auth->user()->token(); 来获取令牌这导致我怀疑令牌对象在创建时没有创建并链接到用户。 但这完全是另一个问题,我希望先解决关于获取用户的部分,然后再解决另一个问题。 【参考方案1】:

此时您不能使用Auth::user(),因为该功能是解决该问题的功能。因此,您需要做的是使用$request->bearerToken() 提取不记名令牌并使用它来检索您的用户。

更新 我看了你的代码,我会推荐以下内容:

建议 API 为“无状态”,这意味着它不应保留任何状态(即 cookie)。最好在每个请求中传递访问令牌并让访问您的 API 的应用程序处理令牌。因此,我建议删除注销功能。然后您可以在AuthServiceProvider 中执行以下操作:

 if ($token_exists) 
     $user = User::find($token->user_id);

     return $user;
 

【讨论】:

这将帮助我获取授权访问令牌,但我如何获取与该访问令牌关联的用户? 这取决于你如何获得你的令牌,你能提供更多信息吗? 我只是通过调用 /oauth/token 和一个 post 请求来获取访问令牌 $client = new Client(); $response = $client->post(sprintf('%s/oauth/token', $this->config->get('app.url')), $formParams); return json_decode((string) $response->getBody(), true); 这是我的web.php中的路由$router->post('/oauth/token', '\Dusterio\LumenPassport\Http\Controllers\AccessTokenController@issueToken'); 更新:我尝试在 AuthServiceProvider 中解码访问令牌,并且能够获取 user_id。从那里,我用 eloquent 检索用户并将用户返回到 logout@LoginController.php。但是,我意识到虽然我可以通过在注销方法中调用 $this->auth->user() 来获取用户,但我仍然无法获取令牌。我做了一个 dd($this->auth->user()) 并且 accessToken 字段仍然是空的。由于某种原因,它似乎与 accessToken 无关。我的用户模型中确实有 HasApiTokens 特征。

以上是关于使用 Laravel Lumen + Passport 获取经过身份验证的用户时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 LUMEN 中使用 GATE 立面(Laravel 6.2)

在没有 Lumen/Laravel 会话的情况下使用 Lumen + Dingo + JWT

lumen和laravel有啥本质区别

Laravel/Lumen - 使用 Model::with()

laravel 和 lumen 有啥区别

无法将 Laravel / Socialite 与 Lumen 一起使用