Laravel 认证模块 auth

一、配置

config/auth.php



return [
    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',//指向llluminate/Auth/SessionGuard.php
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token', //指向llluminate/Auth/TokenGuard.php
            'provider' => 'wx_user',
            'hash' => false,//TokenGuard.php文件类属性
            'input' => 'token', //TokenGuard.php文件类属性
            'storage_key' => 'token', //TokenGuard.php文件类属性
        ],
    ],

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

        'wx_user' => [
            'driver' => 'eloquent',
            'model' =>App\Model\UserModel::class,
        ]
    ],

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

    'password_timeout' => 10800,
];

二、基础使用

Auth::check()  //判断用户是否登陆状态,如果为false,直接重定向到 /login,为什么用Redirect::guest()而不用Redirect::to()呢,通过api手册可以查到:Redirect::guest() 在重定向时会将当前url保存到session中,这样可以在登陆以后,使用Redirect::intended()方法跳转到之前的页面继续业务。
Auth::attempt(array('email' => $email, 'password' => $password)) //attempt 接收一个数组来作为参数1,该参的值将用于寻找数据库中的用户数据。如demo用户将用 email 值在数据库中进行查找,如果用户被找到,在将 password 值进行哈希加密并与数据库中已加密过的密码匹配,如果匹配到,则创建个通过认证的会话给用户。会话获取到后,即视为用户登录成功。当用户身份认证成功 attempt 方法会返回 true,反之则返回 false。
//Auth只是帮助实现了验证逻辑,如果匹配成功会自动帮我们写入session,这样下次Auth::check()的时候就通过了。
//Redirect::intended(‘/’)方法是跳转到之前页面,如果像上面那样使用了Redirect::guest()方法,那么intended这里就会跳转到那时候的url,而它的参数只是一个默认值,再没有记录历史url的时候会跳转到’/’。
//Auth还有些其他方法,如 Auth::basic() 可以实现http basic认证。

三、自定义加密验证

3.1 寻找auth模块

# config/app.php
'aliases' => [
  'App' => Illuminate\Support\Facades\App::class,
  'Artisan' => Illuminate\Support\Facades\Artisan::class,
  'Auth' => Illuminate\Support\Facades\Auth::class,

看到调用Auth其实是调用了 Illuminate\Support\Facades\Auth::class ,打开这个类文件

class Auth extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'auth';
    }
    // ...
}

看到,Auth是通过Facade动态绑定的,绑定到哪里呢,进一步寻找发现
vendor/laravel/framework/src/Illuminate/AuthServiceProvider

class AuthServiceProvider extends ServiceProvider
{
    /**
     * Register the authenticator services.
     *
     * @return void
     */
    protected function registerAuthenticator()
    {
        $this->app->singleton('auth', function ($app) {
            $app['auth.loaded'] = true;
            return new AuthManager($app);
        });
 
        $this->app->singleton('auth.driver', function ($app) {
            return $app['auth']->guard();
        });
    }
}

默认的Auth绑定了AuthManager,打开AuthManager文件

 
namespace Illuminate\Auth;
 
use Closure;
use InvalidArgumentException;
use Illuminate\Contracts\Auth\Factory as FactoryContract;
class AuthManager implements FactoryContract
{
    use CreatesUserProviders;
 
    protected $app;
 
    protected $guards = [];
 
    public function guard($name = null)
    {
        $name = $name ?: $this->getDefaultDriver();
 
        return isset($this->guards[$name])
                    ? $this->guards[$name]
                    : $this->guards[$name] = $this->resolve($name);
    }
 
    public function getDefaultDriver()
    {
        return $this->app['config']['auth.defaults.guard'];
    }
 
    public function __call($method, $parameters)
    {
        return $this->guard()->{$method}(...$parameters);
    }
}

并没找到attempt方法,但有个__call魔术方法,那肯定是他里面,为快速找到他,直接用 dd(get_class($this->guard())); ,真正的attempt究竟被谁调用了呢?打印了SessionGuard,继续找下去 Illuminate\Auth\SessionGuard ,打开该类,发现终于发现了attempt的实现

class SessionGuard implements StatefulGuard, SupportsBasicAuth
{
    use GuardHelpers, Macroable;
    public function attempt(array $credentials = [], $remember = false)
    {
        $this->fireAttemptEvent($credentials, $remember);
 
        $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);
        if ($this->hasValidCredentials($user, $credentials)) {
            $this->login($user, $remember);
 
            return true;
        }
        $this->fireFailedEvent($user, $credentials);
 
        return false;
    }

这就是attempt实现,通过 $this->provider->retrieveByCredentials($credentials)获取用户信息,并验证,如果成功则登录,并返回true,所以我们真正做的密码验证肯定在retrieveByCredentials这个方法里面 Laravel 默认提供了 UserProviderEloquentUserProvider 打开改方法

class EloquentUserProvider implements UserProvider
{
    protected $hasher;
 
    protected $model;
    public function __construct(HasherContract $hasher, $model)
    {
        $this->model = $model;
        $this->hasher = $hasher;
    }
    public function validateCredentials(UserContract $user, array $credentials)
    {
        $plain = $credentials['password'];
        return $this->hasher->check($plain, $user->getAuthPassword());
    }
    public function setHasher(HasherContract $hasher)
    {
        $this->hasher = $hasher;
 
        return $this;
    }
}

所以这里的hasher就是系统默认的BcryptHasher了,我们修改他直接注入自己的haser。ok,了解思路了,开始搞它

3.2 编写自己的密码规则hasher


 
namespace App\Helpers\Hasher;
 
use Illuminate\Contracts\Hashing\Hasher;
 
class MD5Hasher implements Hasher
{
    public function check($value, $hashedValue, array $options = [])
    {
        return $this->make($value) === $hashedValue;
    }

    public function needsRehash($hashedValue, array $options = [])
    {
        return false;
    }
 
    public function make($value, array $options = [])
    {
        $value = env('SALT', '').$value;
        return md5($value);  //这里写你自定义的加密方法
    }
}

3.3 用自己的Hasher替换默认的Hasher

创建MD5HashServiceProvider

php artisan make:provider MD5HashServiceProvider

添加如下方法


 
namespace App\Providers;
 
use App\Helpers\Hasher\MD5Hasher;
use Illuminate\Support\ServiceProvider;
 
class MD5HashServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app->singleton('hash', function () {
            return new MD5Hasher;
        });
    }
 
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
 
    public function provides()
    {
        return ['hash'];
    }
}

然后在config/app.phpproviders中,将 Illuminate\Hashing\HashServiceProvider::class, 替换为 \App\Providers\MD5HashServiceProvider::class,

OK,大功告成

四、auth常用函数


Auth::guard("api")->user();
Auth::guard("api")->check();
Auth::guard("api")->attempt();
Auth::guard("api")->id();

你可能感兴趣的:(laravel)