php - Laravel 5.5 多重身份验证路由问题

标签 php laravel authentication laravel-5 routing

尝试使用 Doctrine 而不是 Eloquent 让 Laravel 多重身份验证工作。我尝试了多种方法,但一直卡住了。我目前定义了两个守卫、两个模型、两个登录 Controller 等。如果我启用其中一个,它们就会工作。如果我同时尝试两者,似乎只有默认守卫有效。当我尝试访问另一个守卫时,我被重定向到错误的登录页面。

如果我转到/login - 按预期工作

如果我去/home(没有登录)- 按预期重定向到/login

如果我去/register- 按预期工作

如果我转到/admin/login - 按预期工作

如果我去/admin/register - 按预期工作

如果我去/admin(没有登录)——失败——应该被重定向到/admin/login,而不是被重定向到/login

我确信我遗漏了一些简单的东西。一切都单独工作。它只是让/admin 路由使用正确的中间件……我想……也许吧?

我的路线文件:

Auth::routes();

// staff authentication routes
Route::group( [ 'middleware' => [ 'web' ] ], function() {
  Route::get( 'admin/login', 'Auth\StaffLoginController@showLoginForm' );
  Route::post( 'admin/login', [ 'as' => 'staff.login', 'uses' => 'Auth\StaffLoginController@login' ] );
  Route::get( 'admin/register', 'Auth\StaffRegisterController@showRegistrationForm' );
  Route::post( 'admin/register', [ 'as' => 'staff.register', 'uses' => 'Auth\StaffRegisterController@register' ] );

  Route::group( [ 'middleware' => [ 'staff' ] ], function() {
    Route::get( '/admin', 'AdminController@index' )->name( 'admin' );
  });
});

Route::get('/home', 'HomeController@index')->name('home');

我已经尝试过各种路线定义,但这是最新的迭代。之前的迭代也没有成功。

我的授权文件:

'defaults' => [
    'guard' => 'web',
    'passwords' => 'users',
],

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

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

    'staff' => [
        'driver' => 'session',
        'provider' => 'adminusers',
    ]
],

'providers' => [
    'users' => [
        'driver' => 'doctrine',
        'model' => App\Users\Customer::class,
    ],
    'adminusers' => [
        'driver' => 'doctrine',
        'model' => App\Users\Staff::class,
    ]
],

'passwords' => [
    'users' => [
        'provider' => 'users',
        'table' => 'password_resets',
        'expire' => 60,
    ],
    'adminusers' => [
        'provider' => 'adminusers',
        'table' => 'password_resets',
        'expire' => 30,
    ],
],

我的 LoginController(与开箱即用的基本相同):

class LoginController extends Controller {
  use AuthenticatesUsers;

  protected $redirectTo = '/home';

  public function __construct() {
    $this->middleware('guest')->except('logout');
  }
}

我的 StaffLoginController:

<?php

class StaffLoginController extends Controller {
  use AuthenticatesUsers;

  protected $redirectTo = '/admin';

  protected $guard = 'staff';

  public function __construct() {
    $this->middleware( 'guest' )->except( 'logout' );
  }

  public function showLoginForm() {
    return view( 'auth.staff.login' );
  }

  public function login( Request $request ) {
    $this->validate( $request, [
      'email' => 'required|email',
      'password' => 'required',
    ]);

    if( auth()->guard( 'staff' )->attempt( [
      'email' => $request->input( 'email' ),
      'password' => $request->input( 'password' ),
    ])) {
      return view( 'staff' );
    } else {
      return view( 'auth.staff.login' )->withErrors( [ 'email' => 'Authentication failed' ] );
    }
  }

  protected function guard() {
    return \Auth::guard( 'staff' );
  }
}

我的管理 Controller :

class AdminController extends Controller {
  public function __construct() {
    $this->middleware( 'auth:staff' );
  }

  public function index() {
    return view( 'staff' );
  }
}

我的 RedirectIfStaffUnauthenticated 中间件(在 Http\Kernel.php routeMiddleware 中注册为 'staff' =>\SNJ\Http\Middleware\RedirectIfStaffUnauthenticated::class, ):

class RedirectIfStaffUnauthenticated {
  public function handle( $request, Closure $next, $guard = 'staff' ) {
    if ( !Auth::guard( $guard )->check() ) {
      return view( 'auth.staff.login' );
    }

    return $next( $request );
  }
}

更新:

将 web.php 中的路由更改为这样(从 admin/login 和 admin/register 路由中删除了中间件:

Auth::routes();

// staff authentication routes
Route::get( 'admin/login', 'Auth\StaffLoginController@showLoginForm' );
Route::post( 'admin/login', [ 'as' => 'staff.login', 'uses' => 'Auth\StaffLoginController@login' ] );
Route::get( 'admin/register', 'Auth\StaffRegisterController@showRegistrationForm' );
Route::post( 'admin/register', [ 'as' => 'staff.register', 'uses' => 'Auth\StaffRegisterController@register' ] );

Route::group( [ 'middleware' => [ 'staff' ] ], function() {
  Route::get( '/admin', 'AdminController@index' )->name( 'admin' );
});

Route::get('/home', 'HomeController@index')->name('home');

没有变化。还是不行。

因此尝试更改路由(将所有管理路由放入“员工”中间件: 验证::路由();

// staff authentication routes

Route::group( [ 'middleware' => [ 'staff' ] ], function() {
  Route::get( 'admin/login', 'Auth\StaffLoginController@showLoginForm' );
  Route::post( 'admin/login', [ 'as' => 'staff.login', 'uses' => 'Auth\StaffLoginController@login' ] );
  Route::get( 'admin/register', 'Auth\StaffRegisterController@showRegistrationForm' );
  Route::post( 'admin/register', [ 'as' => 'staff.register', 'uses' => 'Auth\StaffRegisterController@register' ] );
  Route::get( '/admin', 'AdminController@index' )->name( 'admin' );
});

Route::get('/home', 'HomeController@index')->name('home');

一样一样。还是不行。

最佳答案

将您的 StaffLoginController 更改为此,

    <?php

class StaffLoginController extends Controller {
  use AuthenticatesUsers;

  public function showLoginForm() {
    return view( 'auth.staff.login' );
  }

  public function login( Request $request ) {
    $this->validate( $request, [
      'email' => 'required|email',
      'password' => 'required',
    ]);

    if( auth()->guard( 'staff' )->attempt( [
      'email' => $request->input( 'email' ),
      'password' => $request->input( 'password' ),
    ])) {
      return view( 'staff' );
    } else {
      return view( 'auth.staff.login' )->withErrors( [ 'email' => 'Authentication failed' ] );
    }
  }
}

从 AdminController 中删除构造函数,我们稍后将在路由上调用此中间件。

class AdminController extends Controller {

  public function index() {
    return view( 'staff' );
  }
}

您不需要将保护值传递给 auth 中间件,因为您已经定义了用于验证 admin 路由的第二个中间件。

像这样更新你的员工中间件。

class RedirectIfStaffUnauthenticated {
  public function handle( $request, Closure $next, $guard = null ) {
    if ( Auth::guard( $guard )->check() ) {

if(! $guard == 'staff')
                {
                    return redirect()->route( 'staff.login.form' ); 
                }
     }else return redirect()->route( 'staff.login.form' ); 

    return $next( $request );
  }
}

现在更新你的路线。

Route::get( 'admin/login', 'Auth\StaffLoginController@showLoginForm' );
Route::post( 'admin/login', [ 'as' => 'staff.login.submit', 'uses' => 'Auth\StaffLoginController@login' ] );
Route::get( 'admin/register', 'Auth\StaffRegisterController@showRegistrationForm' );
Route::post( 'admin/register', [ 'as' => 'staff.register.submit', 'uses' => 'Auth\StaffRegisterController@register' ] );
Route::group( [ 'middleware' => [ 'staff' ] ], function() {
  Route::get( '/admin', 'AdminController@index' )->name( 'admin' );
});

同时将以下行添加到 app\ExceptionsHandler.php 文件中的 unauthenticated 函数中

$guard = array_get($exception->guards(), 0);
        switch ($guard) {
      case 'staff':
        $login = 'admin/login';
        break;
    case 'users':
        $login = 'login';
        break;
      default:
        $login = 'login';
        break;
    }
    return redirect()->guest(route('login'));

请检查你的app/Kernel.php,你可以看到guestapp/Http/Middleware/RedirectIfAuthenticated.php的别名> 中间件。

您不需要在 web.php 文件和 Controller 构造函数上调用构造函数。

这里 RedirectIfStaffUnauthenticated 中间件检查根 /admin 是否已通过身份验证,并且它的保护值是 staff,如果没有,它将重定向到/admin/login 路径。

请阅读laravel doc 澄清

希望这对您有所帮助。

关于php - Laravel 5.5 多重身份验证路由问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46270775/

相关文章:

php - 将变量声明为 PHP 类

php - Laravel 事件广播未触发

php - 具有内部连接的 Laravel 作用域

c# - 本地 IIS Express 上的 ASP.NET 应用程序使用事件目录对用户进行身份验证

java - 使用域转发设置登录时出现 HTTP 状态 408 错误

mysql - 密码错误...?

php - 如果启用了 PHP,如何 checkin .htaccess?

java - Java 中的传统加密和 PHP 中的解密

php - 我无法使用 phpdoc [无法打开输入文件 :\phpdoc. php]

php - 在 Laravel 5.7 的子域组中设置命名路由