Laravel的Auth验证Token验证使用自定义Redis的例子


Posted in PHP onSeptember 30, 2019

背景

项目用户量逐渐增大,接口调用次数越来越多,所以决定使用Redis存token,缓解数据库压力

调研

config/auth.php文件中发现用户的驱动使用的是EloquentUserProvider服务提供器,然后查找EloquentUserProvider.php 然后发现在vendor/laravel/framework/src/Illuminate/Auth文件下存在该文件

<?php
 
namespace Illuminate\Auth;
 
use Illuminate\Support\Str;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
 
class EloquentUserProvider implements UserProvider
{
 /**
  * The hasher implementation.
  *
  * @var \Illuminate\Contracts\Hashing\Hasher
  */
 protected $hasher;
 
 /**
  * The Eloquent user model.
  *
  * @var string
  */
 protected $model;
 
 /**
  * Create a new database user provider.
  *
  * @param \Illuminate\Contracts\Hashing\Hasher $hasher
  * @param string $model
  * @return void
  */
 public function __construct(HasherContract $hasher, $model)
 {
  $this->model = $model;
  $this->hasher = $hasher;
 }
 
 /**
  * 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 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();
 }
...
}

实现代码

因为我们是需要在当前的Auth验证基础之上添加一层Redis缓存,所以最简单的办法继承EloquentUserProvider类,重写

retrieveByCredentials方法所以我们新建RedisUserProvider.php文件

<?php
namespace App\Providers;
 
use Illuminate\Auth\EloquentUserProvider;
use Cache;
 
class RedisUserProvider extends EloquentUserProvider
{
 
 public function __construct($hasher, $model)
 {
  parent::__construct($hasher, $model);
 }
 /**
  * Retrieve a user by the given credentials.
  *
  * @param array $credentials
  * @return \Illuminate\Contracts\Auth\Authenticatable|null
  */
 public function retrieveByCredentials(array $credentials)
 {
 
  if (!isset($credentials['token'])) {
   return;
  }
 
  $token = $credentials['token'];
  $redis = Cache::getRedis();
  $userId = $redis->get($token);
  
  return $this->retrieveById($userId);
 }
}

然后在AuthServiceProvider.php文件下修改如下代码

public function boot(GateContract $gate)
 {
  $this->registerPolicies($gate);
 
  //将redis注入Auth中
  Auth::provider('redis',function($app, $config){
   return new RedisUserProvider($app['hash'], $config['model']);
  });
 }

修改config/auth.php用户的auth的驱动为redis。

后续

改完代码以后发现无法正常登录,一直提示用户或密码错误。。。然后看看了下用户认证方法是

auth('web')->once($credentials);然后看是在
Illuminate\Auth\SessionGuard文件中用到了RedisUserProvider文件中retrieveByCredentials方法中对用户进行密码验证,

于是修改RedisUserProvider文件

<?php
namespace App\Providers;
 
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Support\Str;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Cache;
 
class RedisUserProvider extends EloquentUserProvider
{
 
 public function __construct($hasher, $model)
 {
  parent::__construct($hasher, $model);
 }
 /**
  * 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;
  }
  if(isset($credentials['phone']) && isset($credentials['password'])){
   // 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();
  }
 
  $token = $credentials['token'];
  $redis = Cache::getRedis();
  $userId = $redis->get($token);
 
  return $this->retrieveById($userId);
 }
}

然后登录成功啦!皆大欢喜!

以上这篇Laravel的Auth验证Token验证使用自定义Redis的例子就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP&amp;MYSQL服务器配置说明
Oct 09 PHP
分享PHP入门的学习方法
Jan 02 PHP
PHP 身份验证方面的函数
Oct 11 PHP
PHP写UltraEdit插件脚本实现方法
Dec 26 PHP
php array的学习笔记
May 16 PHP
将时间以距今多久的形式表示,PHP,js双版本
Sep 25 PHP
深入eAccelerator与memcached的区别详解
Jun 06 PHP
ASP和PHP实现生成网站快捷方式并下载到桌面的方法
May 08 PHP
Yii净化器CHtmlPurifier用法示例(过滤不良代码)
Jul 15 PHP
详解php中curl返回false的解决办法
Mar 18 PHP
Linux下源码包安装Swoole及基本使用操作图文详解
Apr 02 PHP
通过PHP的Wrapper无缝迁移原有项目到新服务的实现方法
Apr 02 PHP
Laravel框架控制器的middleware中间件用法分析
Sep 30 #PHP
Laravel 已登陆用户再次查看登陆页面的自动跳转设置方法
Sep 30 #PHP
laravel实现登录时监听事件,添加登录用户的记录方法
Sep 30 #PHP
php7下的filesize函数
Sep 30 #PHP
laravel利用中间件防止未登录用户直接访问后台的方法
Sep 30 #PHP
laravel实现Auth认证,登录、注册后的页面回跳方法
Sep 30 #PHP
Laravel框架表单验证操作实例分析
Sep 30 #PHP
You might like
PHP中获取时间的下一周下个月的方法
2014/03/18 PHP
Laravel5.1框架注册中间件的三种场景详解
2019/07/09 PHP
js过滤特殊字符输入适合输入、粘贴、拖拽多种情况
2014/03/22 Javascript
使用postMesssage()实现跨域iframe页面间的信息传递方法
2016/03/29 Javascript
jquery实现下拉框功能效果【实例代码】
2016/05/06 Javascript
微信小程序 详解Page中data数据操作和函数调用
2017/01/12 Javascript
JavaScript实现的XML与JSON互转功能详解
2017/02/16 Javascript
JS/jquery实现一个网页内同时调用多个倒计时的方法
2017/04/27 jQuery
js 两个日期比较相差多少天的实例
2017/10/19 Javascript
JS实现的倒计时恢复按钮点击功能【可用于协议阅读倒计时】
2018/04/19 Javascript
vue实现学生录入系统之添加删除功能
2018/07/11 Javascript
vue数据初始化initState的实例详解
2019/04/11 Javascript
javascript设计模式 ? 状态模式原理与用法实例分析
2020/04/22 Javascript
Vue项目接入Paypal实现示例详解
2020/06/04 Javascript
OpenLayers3实现测量功能
2020/09/25 Javascript
vue实现登录功能
2020/12/31 Vue.js
python 正则表达式 概述及常用字符
2009/05/04 Python
python 从远程服务器下载东西的代码
2013/02/10 Python
Python中的装饰器用法详解
2015/01/14 Python
对numpy中二进制格式的数据存储与读取方法详解
2018/11/01 Python
Python 实现两个服务器之间文件的上传方法
2019/02/13 Python
Python 编程速成(推荐)
2019/04/15 Python
解决阿里云邮件发送不能使用25端口问题
2020/08/07 Python
Python unittest如何生成HTMLTestRunner模块
2020/09/08 Python
HTML5之多线程(Web Worker)
2019/01/02 HTML / CSS
维多利亚的秘密官方旗舰店:VICTORIA’S SECRET
2018/04/02 全球购物
澳大利亚最便宜的网上药房:Chemist Warehouse
2020/01/30 全球购物
Goodee官方商店:迷你投影仪
2021/03/15 全球购物
EJB timer的种类
2014/10/28 面试题
《我为你骄傲》教学反思
2014/02/20 职场文书
《桃林那间小木屋》教学反思
2014/05/01 职场文书
英语课前三分钟演讲稿(6篇)
2014/09/13 职场文书
基于PyQT5制作一个桌面摸鱼工具
2022/02/15 Python
Spring Bean是如何初始化的详解
2022/03/22 Java/Android
Python几种酷炫的进度条的方式
2022/04/11 Python
代码复现python目标检测yolo3详解预测
2022/05/06 Python