14                    
               

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

这是我的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);
    }
}
                   

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

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');
    }); 
});
                   

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

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

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

                       
                                   
改进这个问题                                    
17 年 3 月 31 日 7:37                                
                                   
                               
添加评论                
       

5 个回答   正确答案                    

积极的最老的投票                    
       
16                        
                   

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

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');
});
                       

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

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');
    });
});
                       

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

/**
 * 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');
                       

希望这可以帮助!                        

                                       
改进这个答案                                        
19 年 1 月 5 日 10:15编辑                                    
17 年 3 月 31 日 7:52 回答                                    
                                       
                                   
添加评论                    
       
12                        
                   

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

正确答案                        


                       

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

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

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

                                       
改进这个答案                                        
17 年 6 月 21 日 21:47 回答                                    
                                       
                                   
  • 对我来说,这比使用路由更清晰和更具声明性。当然,这只是个人品味和经验的问题,但我投这个票。 —— 房地产 2018 年 8 月 1 日 21:49                                    
添加评论                    
       
6                        
                   

从 Laravel 7.7 开始,您可以excluded_middleware像这样使用                        

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

    Route::group([
      'prefix' => 'setup',
      'excluded_middleware' => ['checkOnboarding'],
], function () {
        Route::get('/', 'OnboardingController@index')->name('setup');
        Route::post('/settings', 'SettingsController@store');
    }); 
});
                   
                                       
改进这个答案                                        
20 年 8 月 11 日 23:36 回答                                    
                                       
                                   
添加评论                    
       
2                        
                   

有两种方法可以解决这个问题                        

  1. 尝试在路线文件中筛选您的路线 web.php or api.php

  2. 跳过路线 middleware

对于全局中间件(您希望在所有路由之前运行的中间件),您应该在中间件中跳过路由。                        

例如:                        

//add an array of routes to skip santize check
protected $openRoutes = [
    'setup/*',
];

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    if(!in_array($request->path(), $this->openRoutes)){
       //middleware code or call of function
    }       

    return $next($request);
}
                       

对于其他中间件,您可以轻松跳过路由文件并根据中间件对路由进行分组。                        

例如:                        

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');
});
                   
                                       
改进这个答案                                        
20 年 7 月 6 日 6:01 回答                                    
                                       
                                   
添加评论                    
       
1                        
                   

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

//here register routes on which you dont want the middleware: checkOnboarding
Route::group(['middleware' => ['auth','checkOnboarding']], function () {
     //routes on which you want the middleware
});
                   
                                       
改进这个答案                                        
17 年 3 月 31 日 7:49 回答                                    
                                       
                                   
添加评论                    
       

你的答案            

来自 https://stack.com/questions/43135138/apply-middleware-to-all-routes-except-setup-in-laravel-5-4