Laravel 5.1多重身份验证

时间:2015-08-30 08:50:11

标签: laravel authentication laravel-5 laravel-5.1

如何在Laravel 5.1中验证多种类型的用户,例如求职者,招聘人员,行政人员等

有些人建议使用单个用户表来仅存储密码和电子邮件,创建用于存储用户特定信息的配置文件表(jobseeker_profile,recruiter_profile)并使用角色来区分不同类型的用户(即具有角色和role_user)表。

这一切都很好但是如果不同类型的用户具有不同的注册和登录表单会怎样。如何自定义默认的auth控制器以显示正确的视图?

所以,如果我有以下路线:

// Jobseeker Authentication routes...
Route::get('auth/login', 'Auth\AuthController@getLogin');
Route::post('auth/login', 'Auth\AuthController@postLogin');
Route::get('auth/logout', 'Auth\AuthController@getLogout');

// Jobseeker Registration routes...
Route::get('auth/register', 'Auth\AuthController@getRegister');
Route::post('auth/register', 'Auth\AuthController@postRegister');


// Recruiter Authentication routes...
Route::get('recruiter/auth/login', 'Auth\AuthController@getLogin');
Route::post('recruiter/auth/login', 'Auth\AuthController@postLogin');
Route::get('recruiter/auth/logout', 'Auth\AuthController@getLogout');

// Recruiter Registration routes...
Route::get('recruiter/auth/register', 'Auth\AuthController@getRegister');
Route::post('recruiter/auth/register', 'Auth\AuthController@postRegister');

这是开箱即用的默认身份验证控制器:

class AuthController extends Controller
{
    use AuthenticatesAndRegistersUsers;

    public function __construct()
    {
        $this->middleware('guest', ['except' => 'getLogout']);
    }

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => 'required|max:255',
            'email' => 'required|email|max:255|unique:users',
            'password' => 'required|confirmed|min:6',
        ]);
    }

    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
        ]);
    }
}    

默认开箱即用的auth控制器使用的特征:

trait AuthenticatesUsers
{
   use RedirectsUsers;

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

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

        $credentials = $this->getCredentials($request);

        if (Auth::attempt($credentials, $request->has('remember'))) {
            return redirect()->intended($this->redirectPath());
        }

        return redirect($this->loginPath())
            ->withInput($request->only('email', 'remember'))
            ->withErrors([
               'email' => $this->getFailedLoginMessage(),
            ]);
   }

    public function loginPath()
   {
        return property_exists($this, 'loginPath') ? $this->loginPath : '/auth/login';
    }

}

trait RegistersUsers
{
    use RedirectsUsers;

    public function getRegister()
    {
        return view('auth.register');
    }

    public function postRegister(Request $request)
    {
        $validator = $this->validator($request->all());

        if ($validator->fails()) {
            $this->throwValidationException(
                $request, $validator
            );
         }

         Auth::login($this->create($request->all()));

        return redirect($this->redirectPath());
    }
}

我确信这是许多Web应用程序的一个非常常见的要求,但我找不到任何有用的Laravel特定实现教程。由于一些奇怪的原因,所有教程都只关注开箱即用的实现。

非常感谢上述任何帮助。

5 个答案:

答案 0 :(得分:6)

这不是直接解决问题的方法,而是解决问题的另一种方法。

不要为不同的组创建不同的用户名和密码,而是进行具有角色的中央身份验证。它称为用户和角色

您可以定义具有不同角色的组,并且每个角色都具有对相应区域的特定访问权限。

关于注册过程,您可以使用相同的控制器创建两个不同的视图,并且对于每个视图,您可以创建一个隐藏字段,以指示它是求职者组还是招聘组。

两者都会收到两封不同的确认电子邮件,他们应该填写其余的个人资料信息,比如招聘人员应该把公司名称和求职者放在他的名字等等。他们可能有两个不同的表格来提供个人资料信息,但仍然使用相同的登录系统。

通过向中间件和正确的路线添加条件,如果求职者尝试访问招聘人员区域,即使求职者登录系统,求职者也无法访问该区域或相反的方式。

由于Laravel 5.1有build in user login system,所以你几乎没有选择,建立自己的角色或使用第三方。

我建议你建立自己的代码,这样你就可以控制你的代码,并可以随着时间的推移进一步开发它。你可能需要半天的时间才能让它运行并了解它是如何运作的,但是值得花时间用正确的方法而不是你在问题中的方式 OR 使用第三方是好的你也可以搜索很多包。我个人使用了Entrust(https://github.com/Zizaco/entrust),这是为您的项目提供角色和权限的简单方法。

这里也是由Jeffrey Way在Laracast开发的视频链接,它为Laravel 4从头开始构建用户和角色系统。但由于你有用户部分,只需按照角色部分进行小修改,你就会有角色系统到你的Laravel 5.1,我已经尝试过了它的确有效。

关于您在评论中的问题,当您关注视频时,您将理解这个概念。

视频链接:https://laracasts.com/lessons/users-and-roles

您可能需要创建帐户才能观看视频,大部分视频都是免费的。

良好做法 说明你想要实现什么使事情变得更容易也是一个很好的做法,我刚刚为你的项目做了一个例子,但这只是学习的一个例子:

enter image description here

我鼓励您阅读有关角色的一些主题,在这里您还可以找到对Laravel的第三方acl系统的一些启发,可能会有更多文章,但这里有一些:

阅读:
https://laracasts.com/discuss/channels/laravel/which-package-is-best-for-roles-permissions/?page=2
https://laracasts.com/discuss/channels/general-discussion/laravel-5-user-groups-management
https://laracasts.com/discuss/channels/general-discussion/roles-and-permissions-in-laravel-5

修改

重要提示
Laravel 5.1引入了授权,我还没有在网上找到太多的文档,但是花一些时间学习它是值得的:

http://laravel.com/docs/5.1/authorization#policies

NEW UPDATE
有一些很棒的视频解决方案可以满足您的要求,请点击此处的ACL部分 https://laracasts.com/series/whats-new-in-laravel-5-1

这也可能非常有趣: https://laracasts.com/lessons/email-verification-in-laravel

这将为您提供完整自己开发的解决方案。

答案 1 :(得分:1)

通过拉起sarav / laravel-multiauth包

,您可以轻松实现多种身份验证
 composer require sarav/laravel-multiauth

我假设您有Jobseeker,Recruiter,Admin。

的单独表格

第1步:打开app.php并替换

Illuminate\Auth\AuthServiceProvider::class

Sarav\Multiauth\MultiauthServiceProvider::class

然后,打开auth.php文件并删除

<?php

return [

    'driver' => 'eloquent',
    'model'  => 'App\User::class',
    'table'  => 'users',
    'password' => [
       'email' => 'emails.password',
       'table' => 'password_resets',
       'expire' => 60,
    ],
];

并添加以下代码

return [
'multi' => [
    'jobseeker' => [
        'driver' => 'eloquent',
        'model'  => App\Jobseeker::class, // Model Class
        'table'  => 'jobseeker' // jobseeker table
    ],
    'recruiter' => [
        'driver' => 'eloquent',
        'model'  => App\Recruiter::class, // Model Class
        'table'  => 'recruiter' //recruiter table
    ],
    'admin' => [
        'driver' => 'eloquent',
        'model'  => App\Admin::class, // Model Class
        'table'  => 'admin' //admin table
    ],
 ],
 'password' => [
       'email' => 'emails.password',
       'table' => 'password_resets',
       'expire' => 60,
  ]
 ];

多数民众赞成!

现在您可以通过调用

尝试登录尝试
\Auth::attempt('jobseeker', ['email'=> 'johndoe@example.com', 'password' => 'secret']);

\Auth::attempt('recruiter', ['email'=> 'johndoe@example.com', 'password' => 'secret']);

\Auth::attempt('admin', ['email'=> 'johndoe@example.com', 'password' => 'secret']);

永远记住第一个参数应该是您的用户参数。在这里,我给求职者登记尝试,招聘人员招聘人员和管理员登录尝试。如果没有正确的第一个参数,系统将抛出异常。

有关详细信息,请查看本文 http://sarav.co/blog/multiple-authentication-in-laravel-continued/

答案 2 :(得分:0)

简答:将用户类型添加到具有特定号码的用户表中。

  

TL; DR回答。

长答案

  1. 如果您迁移了表格,只需运行php artisan migrate:rollback
  2. 将以下行添加到用户的迁移表中: $table->integer("user_type")->default(0);
  3.   

    这里我认为用户类型零只是一个简单的JobSeeker。

    1. 在您的表单中,您可以添加零值和一个选项,以便人们选择他们想要的招聘人员。没有其他的

答案 3 :(得分:0)

作为另一种解决方案,我建议您使用用户和帐户之间的多态关系,例如

class User extends Eloquent {

  ...

  public function account() {
    return $this->morphTo();
  }

}

class Account extends Eloquent {

  ...

  public function user() {
    return $this->morphOne(App\User::class, 'account');
  }
}

class JobSeeker extends Account { ... }

class Recruiter extends Account { ... }

对于不同类型的帐户,您可以使用路由前缀和不同的身份验证控制器,特别是对于每个帐户实例不同的注册:

// Recruiter Authentication routes...
Route::group(['prefix' => 'recruiter'], function() {
  Route::controller('auth', 'Auth\RecruiterAuthController');
});

最后,您可以直接从auth()->user()->account访问经过身份验证的帐户。它将返回任何Account(Recruiter,Admin,....)

的实例

希望它可以帮助你;)

答案 4 :(得分:0)

我将尝试解释如何在Laravel 5.1中管理身份验证

在应用程序启动时调用AuthServiceProvider,调用创建registerAuthenticator()的{​​{1}}函数。

new AuthManager

在管理器上创建AuthServiceProvider -> registerAuthenticator() -> new AuthManager()函数将被调用,其中将创建新的createNameDriver,其中nameProvider是您在auth配置文件中选择的auth驱动程序。然后,在该功能中,将创建新的name,并将Guard传递给其承包商。 nameProivder中的所有auth函数都将使用该提供程序中的函数来管理auth。提供者实现了Guard

  • UserProvider
  • retrieveById($identifier)
  • retrieveByToken($identifier, $token)
  • updateRememberToken(Authenticatable $user, $token)
  • retrieveByCredentials(array $credentials)

功能

在Laravel 5.1中管理多个身份验证的主要思想是创建新的validateCredentials(Authenticatable $user, array $credentials)并在其启动过程中使用auth new AutServiceProvider,然后将在同一个Guard中使用这些函数。在AuthModelProvider中,您可以按照自己的方式管理所有检索功能。

以下所有内容都已更改,我已经对管理多个身份验证进行了修改。我的项目名称是AuthModelProvider,这就是我到处使用它的原因。

将此功能添加到您的模型

APC

在Provider / YourProjectName目录中创建AuthServiceProvider。在启动函数中,我们从新的提供程序AuthModelProvider扩展auth。

public function getAuthIdentifier()
{
    return [self::MODULE_NAME => $this->getKey()];
}

在同一目录中创建AuthModelProvider。我的模型中的差异是公司表中存在登录字段。但如果你愿意,你可以更具体。在retrieveByCridentials函数中,我只是寻找登录的存在并相应地选择我的模型。

<?php

namespace App\Providers\Apc;

use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Hashing\BcryptHasher;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        self::getAuthModels();
        $this->app['auth']->extend('apc', function() {
            return new AuthModelProvider(self::getAuthModels(), new BcryptHasher());
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {

    }

    public static function getAuthModels()
    {
        $configModels = config('auth.models');
        $authModels = [];
        foreach ($configModels as $key => $class) {
            $authModel = new $class();
            $authModels [$key]=  $authModel;
        }

        return $authModels;
    }
}

将AuthServiceProvider添加到app conf文件。

<?php

namespace App\Providers\Apc;

use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Support\Str;

class AuthModelProvider implements UserProvider
{
    protected $users;

    protected $hasher;

    public function __construct($usersModels, HasherContract $hasher)
    {
        $this->users = $usersModels;
        $this->hasher = $hasher;
    }

    /**
     * Retrieve a user by their unique identifier.
     *
     * @param  mixed $identifier
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveById($identifiers)
    {
        foreach ($identifiers as $key => $id) {
            if (isset($this->users[$key])) {
                return $this->users[$key]->where('id', $id)->active()->base()->first();
            }
        }
    }

    /**
     * Retrieve a user by their unique identifier and "remember me" token.
     *
     * @param  mixed $identifier
     * @param  string $token
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByToken($identifiers, $token)
    {
        return null;
        $user = $this->getUserByIdentifier($identifiers);
        if ($user) {
            return $user->where($user->getRememberTokenName(), $token)->active()->first();
        }
    }

    /**
     * Update the "remember me" token for the given user in storage.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable $user
     * @param  string $token
     * @return void
     */
    public function updateRememberToken(Authenticatable $user, $token)
    {
        $user->setRememberToken($token);
        $user->save();
    }

    /**
     * Retrieve a user by the given credentials.
     *
     * @param  array $credentials
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByCredentials(array $credentials)
    {
        if (empty($credentials)) {
            return null;
        }

        if (isset($credentials['login'])) {
            $userModel = $this->users['company'];
        } else {
            $userModel = $this->users['user'];
        }

        $query = $userModel->newQuery();

        foreach ($credentials as $key => $value) {
            if (! Str::contains($key, 'password')) {
                $query->where($key, $value);
            }
        }

        return $query->first();
    }

    /**
     * Validate a user against the given credentials.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable $user
     * @param  array $credentials
     * @return bool
     */
    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        $plain = $credentials['password'];

        return $this->hasher->check($plain, $user->getAuthPassword());
    }

    private function getUserByIdentifier($identifiers)
    {
        if (!$identifiers) {

        }

        foreach ($identifiers as $namespace => $id) {
            if (isset($this->users[$namespace])) {
                return $this->users[$namespace];
            }
        }
        return null;
    }

}

对auth conf文件进行此更改。

 \App\Providers\Apc\AuthServiceProvider::class,

这就是全部。希望它有所帮助。