将中间件应用于 Laravel 5.4 中除 `setup/*` 之外的所有路由

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43135138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 15:41:33  来源:igfitidea点击:

Apply Middleware to all routes except `setup/*` in Laravel 5.4

phplaravellaravel-5laravel-5.4laravel-middleware

提问by Andy Holmes

I'm experimenting with Middleware in my Laravel application. I currently have it set up to run on every route for an authenticated user, however, I want it to ignore any requests that begin with the setupURI.

我正在我的 Laravel 应用程序中试验中间件。我目前将它设置为在经过身份验证的用户的每条路由上运行,但是,我希望它忽略任何以setupURI开头的请求。

Here is what my CheckOnboardingmiddleware method looks like:

这是我的CheckOnboarding中间件方法的样子:

public function handle($request, Closure $next)
{
    /** 
    * Check to see if the user has completed the onboarding, if not redirect.
    * Also checks that the requested URI isn't the setup route to ensure there isn't a redirect loop.
    */
    if ($request->user()->onboarding_complete == false && $request->path() != 'setup') {
        return redirect('setup');
    } else {
        return $next($request);
    }
}

This is being used in my routes like this:

这是在我的路线中使用的,如下所示:

Route::group(['middleware' => ['auth','checkOnboarding']], function () {
    Route::get('/home', 'HomeController@index');
    Route::get('/account', 'AccountController@index');

    Route::group(['prefix' => 'setup'], function () {
        Route::get('/', 'OnboardingController@index')->name('setup');
        Route::post('/settings', 'SettingsController@store');
    }); 
});

Now, if I go to /homeor /accountI get redirected to /setupas you would expect. This originally caused a redirect loop error hence why & $request->path() != 'setup'is in the Middleware.

现在,如果我去/home/account我被重定向到/setup你所期望的。这最初导致重定向循环错误,因此为什么& $request->path() != 'setup'在中间件中。

I feel like this is a really clunky way of doing it, and obviously doesn't match anything after setuplike the setup/settingsroute I have created.

我觉得这是一种非常笨拙的方式,显然与我创建setupsetup/settings路线不匹配。

Is there a better way to have this Middleware run on all routes for a user, but also set certain routes that should be exempt from this check?

有没有更好的方法让这个中间件在用户的所有路由上运行,但也设置某些应该免于此检查的路由?

回答by Rwd

There's nothing wrong with what you're doing, however, I would suggest splitting your route groups up instead i.e.:

您所做的没有任何问题,但是,我建议将您的路线组分开,即:

Route::group(['middleware' => ['auth', 'checkOnboarding']], function () {
    Route::get('/home', 'HomeController@index');
    Route::get('/account', 'AccountController@index');
});

Route::group(['prefix' => 'setup', 'middleware' => 'auth'], function () {
    Route::get('/', 'OnboardingController@index')->name('setup');
    Route::post('/settings', 'SettingsController@store');
});

Alternatively, have a parent group for your auth:

或者,为您的身份验证设置一个父组:

Route::group(['middleware' => 'auth'], function () {

    Route::group(['middleware' => 'checkOnboarding'], function () {
        Route::get('/home', 'HomeController@index');
        Route::get('/account', 'AccountController@index');
    });

    Route::group(['prefix' => 'setup'], function () {
        Route::get('/', 'OnboardingController@index')->name('setup');
        Route::post('/settings', 'SettingsController@store');
    });
});

This will also mean you can remove the extra condition in your middleware:

这也意味着您可以删除中间件中的额外条件:

/**
 * Check to see if the user has completed the onboarding, if not redirect.
 * Also checks that the requested URI isn't the setup route to ensure there isn't a redirect loop.
 */
return $request->user()->onboarding_complete ? $next($request) : redirect('setup');

Hope this helps!

希望这可以帮助!

回答by bstory

You can utilize the Controller class for this with pretty spectacular results.

您可以使用 Controller 类来获得非常壮观的结果。

If you create a __construct function inside of HTTP/Controllers/Controller.php then you can declare middleware to run on every controller action and even declare exceptions as needed.

如果您在 HTTP/Controllers/Controller.php 中创建一个 __construct 函数,那么您可以声明中间件以在每个控制器操作上运行,甚至可以根据需要声明异常。

class Controller extends BaseController
{
  use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
  public function __construct(){
    $this->middleware('auth',['except' => ['login','setup','setupSomethingElse']]);
  }
}

Be careful not to put any of the standard index, store, update, destroy functions in the exception or you'll open up potential security issues.

请注意不要将任何标准的索引、存储、更新、销毁功能放在异常中,否则您将打开潜在的安全问题。

回答by Learner

Routes on which you dont want the middleware to run , simply put them outside of the function:

您不希望中间件运行的路由,只需将它们放在函数之外:

//here register routes on which you dont want the middleware: checkOnboarding
Route::group(['middleware' => ['auth','checkOnboarding']], function () {
     //routes on which you want the middleware
});