将中间件应用于除Laravel 5.4

时间:2017-03-31 07:37:46

标签: php laravel laravel-5 laravel-5.4 laravel-middleware

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

以下是我的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'在中间件中。

我觉得这是一种非常笨重的做法,显然不会像我setup之后的setup/settings路线那样匹配任何内容。

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

5 个答案:

答案 0 :(得分:9)

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

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

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

小心不要在异常中放置任何标准索引,存储,更新,销毁功能,否则会打开潜在的安全问题。

答案 1 :(得分:8)

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

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

希望这有帮助!

答案 2 :(得分:4)

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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

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