【问题标题】:Can't authenticate against multiple models in Laravel无法针对 Laravel 中的多个模型进行身份验证
【发布时间】:2018-07-03 21:17:14
【问题描述】:

我正在尝试在我的应用程序中为超级管理员和用户(单独的表)设置身份验证,但它的行为不符合预期。针对User 模型的身份验证可以正常工作,但不能针对Superadmin 模型。我的模型如下:

用户.php:

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'username', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

超级管理员.php:

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Superadmin extends Authenticatable
{
    use Notifiable;

    protected $guard = 'superadmin';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'username', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

我的配置/auth.php:

<?php

return [

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

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
        'superadmin' => [
            'driver' => 'session',
            'provider' => 'superadmins',
        ],
        'superadmin-api' => [
            'driver' => 'token',
            'provider' => 'superadmins'
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        'superadmins' => [
            'driver' => 'eloquent',
            'model' => App\Superadmin::class,
        ],
    ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
        'superadmins' => [
            'provider' => 'superadmins',
            'table' => 'password_resets',
            'expire' => 15,
        ],
    ],

];

对我来说似乎是正确的,但显然不是,因为在为超级管理员用户输入正确的凭据后会发生以下情况:

为普通用户输入凭据按预期工作:

任何帮助将不胜感激!

【问题讨论】:

  • 看看vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php 类和vendor\laravel\framework\src\Illuminate\Auth\AuthManager.php 你会看到你需要给'守卫'传递一个名字

标签: php laravel authentication eloquent


【解决方案1】:

如果你去

vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php

你会看到一个名为attemptLogin的方法

哪个有

/**
 * Attempt to log the user into the application.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return bool
 */
protected function attemptLogin(Request $request)
{
    return $this->guard()->attempt(
        $this->credentials($request), $request->filled('remember')
    );
}

现在,如果你使用 guard 方法,它会使用

/**
 * Get the guard to be used during authentication.
 *
 * @return \Illuminate\Contracts\Auth\StatefulGuard
 */
protected function guard()
{
    return Auth::guard();
}

现在,如果您进一步研究

vendor\laravel\framework\src\Illuminate\Auth\AuthManager.php 你会看到“守卫方法”需要$name

/**
 * Attempt to get the guard from the local cache.
 *
 * @param  string  $name
 * @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
 */
public function guard($name = null)
{
    $name = $name ?: $this->getDefaultDriver();

    return $this->guards[$name] ?? $this->guards[$name] = $this->resolve($name);
}

现在,看看getDefaultDriver 方法,它从 auth 配置文件中获取默认值:

/**
 * Get the default authentication driver name.
 *
 * @return string
 */
public function getDefaultDriver()
{
    return $this->app['config']['auth.defaults.guard'];
}

在你的 auth.php 中添加:

'login' => [
    'guard' => [
        'web',
    ]
],

因此,在您的 logincontroller.php 中,您可以覆盖保护方法以使用您的特定保护:

<?php

namespace App\Http\Controllers\Auth;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Modules\Core\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }


    /**
     * Attempt to log the user into the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    protected function attemptLogin(Request $request)
    {
        foreach(config('auth.login.guard') as $guard) {
            return $this->guard($guard)->attempt(
                $this->credentials($request), $request->filled('remember')
            );
        }

        return false;
    }

        /**
     * Send the response after the user was authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    protected function sendLoginResponse(Request $request)
    {
        $request->session()->regenerate();

        $this->clearLoginAttempts($request);

        foreach(config('auth.login.guard') as $guard) {
            return $this->authenticated($request, $this->guard()->user())
                    ?: redirect()->intended($this->redirectPath());
        }

        return false;
    }

        /**
     * Log the user out of the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function logout(Request $request)
    {
        foreach(config('auth.login.guard') as $guard) {
            $this->guard($guard)->logout();
        }

        $request->session()->invalidate();

        return redirect('/');
    }

    /**
     * Get the guard to be used during authentication.
     *
     * @return \Illuminate\Contracts\Auth\StatefulGuard
     */
    protected function guard($name = null)
    {
        return Auth::guard($name);
    }

}

【讨论】:

  • 谢谢,但是将此方法添加到 LoginController.php 会导致以下错误: Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_ERROR) Class 'App\Http\Controllers\Auth\Auth' not found
  • 你需要包含auth门面,在顶部use Illuminate\Support\Facades\Auth;
  • 好的,现在它工作得更好了,但仍然不太正确。我不再收到“错误的凭据”消息,但我立即被重定向回登录页面并且没有登录。此外,现在这使得我无法以普通用户身份登录,对吗?
  • “你可以覆盖它,从所有 3 中选择,使用自定义选择”,我对你的意思有点困惑。
  • @BrandonM。查看更新的答案,在 auth.php 中将你的警卫添加到新数组中。
猜你喜欢
  • 2021-02-28
  • 2017-06-14
  • 1970-01-01
  • 2020-07-07
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多