laravel自定义用户认证

   2016-12-23 0
核心提示:2016 年 12 月 23 日PHP Standard添加自定义的 Guard需要通过Auth门面的extend方法定义自己的认证guard,在App\Providers\AuthServiceProvider的boot方法中实现:public function boot(){$this-registerPolicies();Auth::extend('XXX', function($app, $name,

2016 年 12 月 23 日PHP Standard

添加自定义的 Guard

需要通过Auth门面的extend方法定义自己的认证guard,在App\Providers\AuthServiceProvider的boot方法中实现:

public function boot()
{
    $this->registerPolicies();

    Auth::extend('XXX', function($app, $name, array $config) {
        // 返回 Illuminate\Contracts\Auth\Guard 实例
        $guard = new XXXGuard($name,Auth::createUserProvider($config['provider']),$this->app['session.store']);
        //事件
        if (method_exists($guard, 'setDispatcher')) {
            $guard->setDispatcher($this->app['events']);
        }
        //请求
        if (method_exists($guard, 'setRequest')) {
            $guard->setRequest($this->app->refresh('request', $guard, 'setRequest'));
        }
        return $guard;
    });
}

传递给 extend 方法的闭包回调需要返回 Illuminate\Contracts\Auth\Guard 的实现实例,该接口包含了自定义认证 guard 需要的一些方法:

<?php
namespace App\Services\Auth;
use Illuminate\Auth\Events\Authenticated;
use Illuminate\Auth\Events\Failed;
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Attempting;
use Illuminate\Auth\Events\Logout;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Events\Dispatcher;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

class XXXGuard implements Guard
{
    use GuardHelpers;

    protected $session;
    protected $name;
    protected $loggedOut = false;
    protected $request;
    protected $events;

    public function __construct($name,UserProvider $provider,SessionInterface $session,Request $request = null)
    {
        $this->name = $name;
        $this->provider = $provider;
        $this->session = $session;
        $this->request = $request;
    }

    /**
     * Attempt to authenticate a user using the given credentials.
     *
     * @param  array  $credentials
     * @param  bool   $remember
     * @param  bool   $login
     * @return bool
     */
    public function attempt(array $credentials = [], $remember = false, $login = true)
    {
        $this->fireAttemptEvent($credentials, $remember, $login);
        $user = $this->provider->retrieveByCredentials($credentials);
        if ($this->hasValidCredentials($user, $credentials)) {
            if ($login) {
                $this->login($user, $remember);
            }
            return true;
        }
        if ($login) {
            $this->fireFailedEvent($user, $credentials);
        }
        return false;
    }

    /**
     * Determine if the user matches the credentials.
     *
     * @param  mixed  $user
     * @param  array  $credentials
     * @return bool
     */
    protected function hasValidCredentials($user, $credentials)
    {
        return ! is_null($user) && $this->provider->validateCredentials($user, $credentials);
    }

    /**
     * Log a user into the application.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  bool  $remember
     * @return void
     */
    public function login(Authenticatable $user, $remember = false)
    {
        $this->updateSession($user->getAuthIdentifier());

        // If we have an event dispatcher instance set we will fire an event so that
        // any listeners will hook into the authentication events and run actions
        // based on the login and logout events fired from the guard instances.
        $this->fireLoginEvent($user, $remember);
        $this->setUser($user);
    }

    /**
     * Update the session with the given ID.
     *
     * @param  string  $id
     * @return void
     */
    protected function updateSession($id)
    {
        $this->session->set($this->getName(), $id);

        $this->session->migrate(true);
    }

    /**
     * Get a unique identifier for the auth session value.
     *
     * @return string
     */
    public function getName()
    {
        return 'login_'.$this->name.'_'.sha1(static::class);
    }


    /**
     * Get the currently authenticated user.
     *
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function user()
    {
        if ($this->loggedOut) {
            return;
        }

        // If we've already retrieved the user for the current request we can just
        // return it back immediately. We do not want to fetch the user data on
        // every call to this method because that would be tremendously slow.
        if (! is_null($this->user)) {
            return $this->user;
        }

        $id = $this->session->get($this->getName());
        // First we will try to load the user using the identifier in the session if
        // one exists. Otherwise we will check for a "remember me" cookie in this
        // request, and if one exists, attempt to retrieve the user using that.
        $user = null;

        if (! is_null($id)) {
            if ($user = $this->provider->retrieveById($id)) {
                $this->fireAuthenticatedEvent($user);
            }
        }

        return $this->user = $user;
    }

    public function id()
    {
        if ($this->loggedOut) {
            return;
        }

        if ($this->user()) {
            return $this->user()->getAuthIdentifier();
        }

        return $this->session->get($this->getName());
    }

    /**
     * Validate a user's credentials.
     *
     * @param  array  $credentials
     * @return bool
     */
    public function validate(array $credentials = [])
    {
        return $this->attempt($credentials, false, false);
    }

    /**
     * Fire the login event if the dispatcher is set.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  bool  $remember
     * @return void
     */
    protected function fireLoginEvent($user, $remember = false)
    {
        if (isset($this->events)) {
            $this->events->fire(new Login($user, $remember));
        }
    }

    /**
     * Fire the authenticated event if the dispatcher is set.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @return void
     */
    protected function fireAuthenticatedEvent($user)
    {
        if (isset($this->events)) {
            $this->events->fire(new Authenticated($user));
        }
    }

    /**
     * Fire the attempt event with the arguments.
     *
     * @param  array  $credentials
     * @param  bool  $remember
     * @param  bool  $login
     * @return void
     */
    protected function fireAttemptEvent(array $credentials, $remember, $login)
    {
        if (isset($this->events)) {
            $this->events->fire(new Attempting(
                $credentials, $remember, $login
            ));
        }
    }

    /**
     * Fire the failed authentication attempt event with the given arguments.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable|null  $user
     * @param  array  $credentials
     * @return void
     */
    protected function fireFailedEvent($user, array $credentials)
    {
        if (isset($this->events)) {
            $this->events->fire(new Failed($user, $credentials));
        }
    }


    /**
     * Log the user out of the application.
     *
     * @return void
     */
    public function logout()
    {
        $user = $this->user();

        // If we have an event dispatcher instance, we can fire off the logout event
        // so any further processing can be done. This allows the developer to be
        // listening for anytime a user signs out of this application manually.
        $this->clearUserDataFromStorage();

        if (isset($this->events)) {
            $this->events->fire(new Logout($user));
        }

        // Once we have fired the logout event we will clear the users out of memory
        // so they are no longer available as the user is no longer considered as
        // being signed into this application and should not be available here.
        $this->user = null;

        $this->loggedOut = true;
    }

    /**
     * Remove the user data from the session and cookies.
     *
     * @return void
     */
    protected function clearUserDataFromStorage()
    {
        $this->session->remove($this->getName());
    }

    /**
     * Get the event dispatcher instance.
     *
     * @return \Illuminate\Contracts\Events\Dispatcher
     */
    public function getDispatcher()
    {
        return $this->events;
    }

    /**
     * Set the event dispatcher instance.
     *
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
     * @return void
     */
    public function setDispatcher(Dispatcher $events)
    {
        $this->events = $events;
    }

    /**
     * Get the session store used by the guard.
     *
     * @return \Illuminate\Session\Store
     */
    public function getSession()
    {
        return $this->session;
    }

    /**
     * Get the user provider used by the guard.
     *
     * @return \Illuminate\Contracts\Auth\UserProvider
     */
    public function getProvider()
    {
        return $this->provider;
    }

    /**
     * Set the user provider used by the guard.
     *
     * @param  \Illuminate\Contracts\Auth\UserProvider  $provider
     * @return void
     */
    public function setProvider(UserProvider $provider)
    {
        $this->provider = $provider;
    }

    /**
     * Return the currently cached user.
     *
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function getUser()
    {
        return $this->user;
    }

    /**
     * Set the current user.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @return $this
     */
    public function setUser(Authenticatable $user)
    {
        $this->user = $user;

        $this->loggedOut = false;

        $this->fireAuthenticatedEvent($user);

        return $this;
    }

    public function setRequest(Request $request)
    {
        $this->request = $request;

        return $this;
    }
}

定义好自己的认证 guard 之后,可以在配置文件 auth.php 的 guards 配置中使用话这个 guard:

'guards' => [
    'api' => [
        'driver' => 'XXX',
        'provider' => 'users',
    ],
],

添加自定义用户提供者

同样在App\Providers\AuthServiceProvider的boot方法中实现:

public function boot()
{
    $this->registerPolicies();
    //
    Auth::provider('YYY', function($app, array $config) {
        // 返回 Illuminate\Contracts\Auth\UserProvider实例
        return new YYYProvider($config['model']);
    });
}

定义提供者,返回Illuminate\Contracts\Auth\UserProvider的实现实例:

<?php
namespace App\Services\Auth;

use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Support\Str;

class YYYProvider implements UserProvider
{
    protected $model;

    public function __construct($model)
    {
        $this->model = $model;
    }

    public function createModel()
    {
        $class = '\\'.ltrim($this->model, '\\');

        return new $class;
    }

    /**
     * Retrieve a user by their unique identifier.
     *
     * @param  mixed  $identifier
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveById($identifier)
    {
        return $this->createModel()->newQuery()->find($identifier);
    }

    /**
     * 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($identifier, $token)
    {
        //todo 根据token实现记住功能
        return null;
    }

    /**
     * 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)
    {
        //code
    }

    /**
     * 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;
        }
        // First we will add each credential element to the query as a where clause.
        // Then we can execute the query and, if we found a user, return it in a
        // Eloquent User "model" that will be utilized by the Guard instances.
        $query = $this->createModel()->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 $user->Password==md5($plain);
    }

    /**
     * Gets the name of the Eloquent user model.
     *
     * @return string
     */
    public function getModel()
    {
        return $this->model;
    }

    /**
     * Sets the name of the Eloquent user model.
     *
     * @param  string  $model
     * @return $this
     */
    public function setModel($model)
    {
        $this->model = $model;

        return $this;
    }
}

之后可以在配置文件 config/auth.php 中切换到新的用户提供者

'providers' => [
    'users' => [
        'driver' => 'YYY',
    ],
],

然后,就可以在你的 guards 配置中使用这个提供者。

完结

null

 
标签: Laravel
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • nginx 各类网站设置 (laravel , thinkphp , nod
    基础部分设置[root@centos ~]# vim /opt/nginx/conf/nginx.confuser www www;worker_processes auto;pid logs/nginx.pid;worker_rlimit_nofile 100000;events {use epoll;multi_accept on;worker_connections 65535 ;}http {include mime.types;default_type
    02-09
  • PHP trait 特性在 Laravel 中的使用个人心得
    trait 是在PHP5.4中为了方便代码复用的一种实现方式,但目前我在看的的PHP项目中较少看的有程序员去主动使用这个实现方式,在laravel中有很多 trait 的使用,关于trait 在 laravel 的使用请参看 Laravel 在哪些地方用了 trait?我曾在 Laravel 中大型项目面向
    02-09
  • 让我们用 laravel-mix 为 TypeScript 和 Sass
    介绍前端编译TypeScript、Sass、模板引擎等时经常用到Gulp和webpack。这是我个人的印象,但它们似乎都难以管理,因为它们的描述往往复杂而冗长。我不想积极进行,因为我要担心加载器的顺序并且有很多配置选项,我必须花时间去了解它们。我想推荐那里laravel
  • PHP Laravel软删除的实现方法介绍
    用Laravel 自带的 Eloquent ORM 来实现软删除。首先在数据迁移文件中添加删除时间字段./database/migrations/2014_10_12_000000_create_users_table.php?phpuse Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint;use Illu
  • Laravel中如何使用PHP的装饰器模式 php laravel
    本文小编为大家详细介绍“Laravel中如何使用PHP的装饰器模式”,内容详细,步骤清晰,细节处理妥当,希望这篇“Laravel中如何使用PHP的装饰器模式”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。装饰器模式定义:它可以帮助您在
    02-08 laravelphp
  • PHP laravel使用自定义邮件类实现发送邮件
    PHP laravel使用自定义邮件类实现发送邮件
    当登录邮箱为腾讯企业邮箱的时候。Phpmailer发送邮件就不好用了,具体哪里不好用,我没真没找到。但是,邮件得发啊,怎么办呢?我这里搞了一个自定义的发送邮件类,腾讯企业邮箱也可用。但是,邮件发送失败,不会返回报错信息,这个可能是有点坑。源码如下:?
  • 详解PHP laravel中的加密与解密函数
    目录一:简介二:配置三:使用加密/解密1:加密2:不使用序列化进行加密3:解密Laravel为我们提供了完整的加密方法及加密模式。我之前一般在加密的时候使用的是我自己写的加密函数,但是这个玩意,有的位置还是不太使用,当然,破解的话,基本上也是不可能的
  • PHP laravel缓存cache机制详解
    目录一、访问多个缓存存储二、从缓存中获取数据1.获取数据并设置默认值2.检查缓存项是否存在3.数值增加/减少4.获取存储5.获取删除三、缓存中存储数据1.获取存储数据2.缓存不存在时存储数据3.永久存储数据四、从缓存中移除数据Laravel中的cache为我们提供了三
  • PHP laravel实现导出PDF功能
    PHP laravel实现导出PDF功能
    目录一、laravel-tcpdf二、tcpdf三、TCPDF解决保存中文文件名的方法补充一、laravel-tcpdf导出PDF文件Laravel框架为我们集成了一个插件tcpdf。下载地址:https://github.com/elibyy/tcpdf-laravel然后使用composer进行安装就可以了。具体安装过程,请查看文末
  • PHP laravel缓存cache机制怎么实现
    今天小编给大家分享一下PHP laravel缓存cache机制怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Laravel中的cache为我们
点击排行