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 5.0对象模型深度探索之对象复制
Mar 27 PHP
新安装的MySQL数据库需要注意的安全知识
Jul 30 PHP
discuz的php防止sql注入函数
Jan 17 PHP
php判断GIF图片是否为动画的方法
Sep 04 PHP
php实现两个数组相加的方法
Feb 17 PHP
php实现随机生成易于记忆的密码
Jun 19 PHP
Zend Framework实现多文件上传功能实例
Mar 21 PHP
PHP处理数组和XML之间的互相转换
Jun 02 PHP
Thinkphp结合ajaxFileUpload实现异步图片传输示例
Mar 13 PHP
PHP implode()函数用法讲解
Mar 08 PHP
Laravel如何自定义command命令浅析
Mar 23 PHP
PHP生成随机字符串实例代码(字母+数字)
Sep 11 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源码 fsockopen获取网页内容实例详解
2016/09/24 PHP
用Div仿showModalDialog模式菜单的效果的代码
2007/03/05 Javascript
弹出层之1:JQuery.Boxy (一) 使用介绍
2011/10/06 Javascript
javascript静态页面传值的三种方法分享
2013/11/12 Javascript
Nodejs使用mysql模块之获得更新和删除影响的行数的方法
2014/03/18 NodeJs
JavaScript中的单引号和双引号报错的解决方法
2014/09/01 Javascript
JavaScript简单表格编辑功能实现方法
2015/04/16 Javascript
Uploadify上传文件方法
2016/03/16 Javascript
nodejs 的 session 简单使用
2016/06/06 NodeJs
JS常用字符串方法(推荐)
2021/01/15 Javascript
js中class的点击事件没有效果的解决方法
2016/10/13 Javascript
js实现3D图片展示效果
2017/03/09 Javascript
JQuery和html+css实现带小圆点和左右按钮的轮播图实例
2017/07/22 jQuery
angularjs实现柱状图动态加载的示例
2017/12/11 Javascript
JavaScript回调函数callback用法解析
2020/01/14 Javascript
js实现滚动条自动滚动
2020/12/13 Javascript
[01:27:30]LGD vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
Python数据类型学习笔记
2016/01/13 Python
利用TensorFlow训练简单的二分类神经网络模型的方法
2018/03/05 Python
Python实现的将文件每一列写入列表功能示例【测试可用】
2018/03/19 Python
钉钉群自定义机器人消息Python封装的实例
2019/02/20 Python
python基础梳理(一)(推荐)
2019/04/06 Python
Flask框架模板继承实现方法分析
2019/07/31 Python
Python中remove漏删和索引越界问题的解决
2020/03/18 Python
override和overload的区别
2016/03/09 面试题
事业单位个人应聘自荐信
2013/09/21 职场文书
高三地理教学反思
2014/01/11 职场文书
股权转让意向书
2014/04/01 职场文书
销售团队口号大全
2014/06/06 职场文书
广告公司文案策划岗位职责
2015/04/14 职场文书
放假通知范文
2015/04/14 职场文书
青年志愿者服务活动总结
2015/05/06 职场文书
2019新员工心得体会
2019/06/25 职场文书
一文搞懂redux在react中的初步用法
2021/06/09 Javascript
Sleuth+logback 设置traceid 及自定义信息方式
2021/07/26 Java/Android
navicat 连接Ubuntu虚拟机的mysql的操作方法
2022/04/02 MySQL