用户会话认证的 Laravel API 路由

Posted

技术标签:

【中文标题】用户会话认证的 Laravel API 路由【英文标题】:Laravel API routes authenticated by user session 【发布时间】:2017-11-26 09:32:28 【问题描述】:

我已经开始处理现有的 Laravel 5.2 项目。我需要为应用程序的前端构建一些基本的 API 请求以与数据库通信。这些路由需要经过用户会话的认证。

我尝试使用 auth:api 驱动程序设置中间件,并在 ../config/auth.php 中将 api['driver'] 设置为 'session'。但是,即使用户已通过所有权限和角色的身份验证,我仍会不断收到 302 重定向到登录页面。

有人可以推荐一些关于如何基于用户会话实现API身份验证的阅读或其他解决方案吗?

来自路由/api.php:

Route::group(["middleware" => ["auth:api"]], function () 
    // results in 302 redirect to /login
    Route::get('test', function()
        return "TEST";
    );    

);

来自配置/auth.php

'guards' => [
'web' => [
    'driver' => 'session',
    'provider' => 'users',
],

'api' => [
    'driver' => 'session',
    'provider' => 'users',
],

app/Http/Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel

    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \App\Http\Middleware\NoCache::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'role' => \Zizaco\Entrust\Middleware\EntrustRole::class,
        'permission' => \Zizaco\Entrust\Middleware\EntrustPermission::class,
        'ability' => \Zizaco\Entrust\Middleware\EntrustAbility::class,
        'dashboard' => \App\Http\Middleware\dashboardMiddleware::class,
        'system' => \App\Http\Middleware\systemMiddleware::class
    ];

【问题讨论】:

发布您的代码示例。听起来中间件可能设置不正确。可能是你的路由层次结构有点混乱 @JackGal 我已经为你添加了代码副本。 您是否尝试从浏览器访问此类路由? @JackGal 我尝试从浏览器访问,但我认为需要标题“Accept-Encoding application/json”,所以我还将浏览器请求复制为 curl,导入邮递员,并将该标头更改为上面(使用此方法复制 cookie 文件)。 302 重定向到“/login”也会出现同样的问题。 好的.. 你可以在你的内核类中包含你的中间件组的一部分吗?我想看看你的设置是否正确 【参考方案1】:

这是一篇旧帖子,但根据我的经验和我了解到的情况,我们不会对来自第三方应用程序 b/c 基于会话的身份验证的 API 请求使用基于会话的机制身份验证,就像您尚未通过身份验证一样(就像尚未登录一样),它会将您重定向到登录页面(就像这个问题的作者所说的“将 302 重定向到登录页面”)。

但是 API 请求是 XMLHttpRequest(ajax 请求),而不是浏览器请求,如果是,它如何将您重定向到登录页面? (查看开发者工具中的网络选项卡,您会看到,此请求的响应为 302,响应正文为登录 html 页面)。

因此,我们应该只使用基于令牌的 API 身份验证机制,它会以 json 响应返回“您未通过身份验证”之类的消息,供您的 3rd 方应用使用。

对于 laravel,你可以使用 session provider 来做 api guard,但是你需要去 Kernel.php 并添加

\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Session\Middleware\StartSession::class

, 这是基于 laravel 会话的身份验证的核心, 到您的 api 中间件组。否则,即使您已经登录,您仍然无法通过身份验证 因为默认情况下,laravel api 路由没有必要的中间件来进行基于会话的身份验证。

 protected $middlewareGroups = [ 
        'web' => [
            // ...
        ],  

        'api' => [
            \App\Http\Middleware\EncryptCookies::class,          // <------- ADD THIS
            \Illuminate\Session\Middleware\StartSession::class, // <------ ADD THIS
            // ...
        ],  
    ];

参考: https://laracasts.com/discuss/channels/laravel/protecting-api-routes-with-session-guard https://laravel.io/forum/02-09-2016-52-ajax-auth-not-picking-up-session

【讨论】:

【参考方案2】:

问题是您没有在请求中传递任何身份验证标头,因此,很明显它会将您重定向到登录屏幕,即使您使用邮递员点击 API。

为了证明这一点,请尝试从路由文件中的以下行 Route::group(["middleware" =&gt; ["auth:api"]], ... 中删除 auth 中间件,如果您点击测试路由,您应该能够获得 TEST 作为响应。另外,请记住,我们的 api 会自动将 api/ 前缀绑定到所有 api 路由。因此,您应该向/api/test 提出请求,然后您应该得到 TEST。

如果您想在您的 api 中包含身份验证,请阅读Laravel's Passport docs。如果您想要更简单的东西,请从 docs 中的 onceBasic Auth 中间件开始。

我希望这会为您指明正确的方向!

如果您有任何其他问题,请告诉我。

干杯!

【讨论】:

我认为这是“会话”驱动程序的重点?它会从cookie中获得授权吗?

以上是关于用户会话认证的 Laravel API 路由的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 为外部用户登录成功设置会话或令牌 - 无用户仅数据库 Api 用户

如何让会话在 Laravel api 路由中工作?

Laravel6.0 使用 Jwt-auth 实现多用户接口认证

同时认证带来的Laravel 5.8会话混乱

将 Vue js 前端和 laravel 后端(api 路由)托管到共享服务器?

Laravel - 保护 API 路由