【问题标题】:Is there a way to use two authentication middlewares in laravel?有没有办法在 laravel 中使用两个身份验证中间件?
【发布时间】:2020-08-08 15:52:15
【问题描述】:

我在 Laravel 和基本身份验证中实现了护照身份验证。 我有 UserController 在里面,我有构造方法:

 public function __construct()
    {
        $this->middleware('auth.basic.once')->except(['index', 'show']);   
        $this->middleware('auth:api')->except(['index', 'show']); 
    }

OnceBasic 中间件:

public function handle($request, Closure $next)
    {
        if(Auth::guard('api')->check())
        return $next($request);
        else
        return Auth::onceBasic() ?: $next($request);
    }

在OnceBasic 中间件中,我能够检查用户是否使用auth:api 进行了身份验证,然后我阻止身份验证尝试使用onceBasic,因此在使用访问令牌时它可以正常工作。但是在尝试使用 onceBasic(email, password) 进行身份验证时失败,因为 auth:api 也尝试进行身份验证并且它失败了(尝试在默认 \App\Http\Middleware\Authenticate.php 中调用 redirectTo() 方法)

我的问题是有没有办法同时使用这两个中间件,只成功验证一个而阻止另一个工作?

【问题讨论】:

  • Web 和 api 调用不应使用相同的路由。
  • API 的两个中间件,用户可以使用 API 生成他们的个人访问令牌,我没有网络或用户界面 @Tpojka
  • 我想,您希望在注册路线上有某种客人。因此,您在期待客人的端点上不需要任何“身份验证”中间件。
  • 我正在为教育目的进行一些测试,所以我正在尝试应用逻辑:用户可以使用他们的凭据或他们的访问令牌对同一路由进行身份验证。 @Tpojka
  • @Tpojka 我成功应用了这个逻辑的一半,如果用户拥有有效的访问令牌,则跳过对其身份的身份验证。

标签: php laravel authentication middleware laravel-passport


【解决方案1】:

我为两个守卫使用同一个控制器的方法需要将两组不同的路由指向控制器。我在answer to a similar question 中提供了一个示例,这里又是示例代码:

<?php

    Route::middleware(['auth:admin_api'])->group(function () {
        Route::prefix('admin')->group(function () {
            Route::name('api.admin.')->group(function () {

                ////////////////////////////////////////////////////////////
                /// PLACE ADMIN API ROUTES HERE ////////////////////////////
                ////////////////////////////////////////////////////////////
                Route::apiResource('test','App\Http\Controllers\API\MyController');
                ////////////////////////////////////////////////////////////
            });
        });
    });

    Route::middleware(['auth:api'])->group(function () {
        Route::name('api.')->group(function () {
            ////////////////////////////////////////////////////////////
            /// PLACE PUBLIC API ROUTES HERE ///////////////////////////
            ////////////////////////////////////////////////////////////
            Route::apiResource('test', 'App\Http\Controllers\API\MyController');
            ////////////////////////////////////////////////////////////
        });
    });

因此,当管理员用户进入 admin/test 时,它使用 admin auth 保护,而当普通用户进入 /test 时,它使用标准 auth 保护。两者都使用相同的控制器。

然后我为我的应用创建了一个基本控制器。以下是我在构造函数中使用 guard 来访问路由的方式:

<?php


use Illuminate\Http\Response;
use App\Http\Controllers\Controller;

class BaseController extends Controller
{
    protected $user;

    protected $isAdmin = false;

    public function __construct()
    {
        if(Auth::guard('admin_api')->check()) {
            $this->user = Auth::guard('admin_api')->user();
            $this->isAdmin = true;
        } elseif(Auth::guard('api')->check()) {
            $this->user = Auth::guard('api')->user();
            $this->isAdmin = false;
        } else {
            return response()->json([
                'message' => 'Not Authorized',
            ], 401);
        }
    }

【讨论】:

  • 我突然想到使用这种方法,因此我们实际上使用不同的路由端点连接到第二个中间件,但是目前,我有很多路由,复制它们会大大增加大小。让我们等待其他想法。如果没有,我会将这种方法作为唯一的选择。谢谢。
  • 我肯定有兴趣看到另一种方法,但这对我有用。使用资源路由并坚持方法命名约定有助于我保持路由文件井井有条。
  • 谢谢@mchljams,我知道这种方法会奏效,但这不是我正在寻找的方法,所以我不会使用它。但是,我会将您的答案标记为已接受并投票。再次感谢
猜你喜欢
  • 1970-01-01
  • 2020-04-24
  • 1970-01-01
  • 2023-03-02
  • 2019-04-16
  • 2016-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多