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 相关文章推荐
深入解析Session是否必须依赖Cookie
Aug 02 PHP
Smarty模板学习笔记之Smarty简介
May 20 PHP
PHP中多维数组的foreach遍历示例
Jun 13 PHP
php中字符查找函数strpos、strrchr与strpbrk用法
Nov 18 PHP
php中Socket创建与监听实现方法
Jan 05 PHP
php 批量查询搜狗sogou代码分享
May 17 PHP
PHP获得数组交集与差集的方法
Jun 10 PHP
Zend Framework入门教程之Zend_Registry组件用法详解
Dec 09 PHP
PHP获取文件扩展名的方法实例总结
Jun 10 PHP
PHP封装的XML简单操作类完整实例
Nov 13 PHP
php面向对象程序设计中self与static的区别分析
May 21 PHP
Laravel 微信小程序后端搭建步骤详解
Nov 26 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
利用static实现表格的颜色隔行显示
2006/10/09 PHP
php中实现记住密码下次自动登录的例子
2014/11/06 PHP
php计算年龄精准到年月日
2015/11/17 PHP
php抽象方法和普通方法的区别点总结
2019/10/13 PHP
laravel接管Dingo-api和默认的错误处理方式
2019/10/25 PHP
JavaScript对象之间的转换 jQuery对象和原声DOM
2011/03/07 Javascript
javascript学习笔记(三)显示当时时间的代码
2011/04/08 Javascript
输入自动提示搜索提示功能的使用说明:sugggestion.txt
2013/09/02 Javascript
javascript的propertyIsEnumerable()方法使用介绍
2014/04/09 Javascript
jquery动态添加删除(tr/td)
2015/02/09 Javascript
JS实现带缓冲效果打开、关闭、移动一个层的方法
2015/05/09 Javascript
jQuery实现图片上传和裁剪插件Croppie
2015/11/29 Javascript
基于jQuery实现多标签页切换的效果(web前端开发)
2016/07/24 Javascript
AngularJS模块详解及示例代码
2016/08/17 Javascript
微信js-sdk预览图片接口及从拍照或手机相册中选图接口用法示例
2016/10/13 Javascript
浅谈JavaScript的计时器对象
2016/12/26 Javascript
vue2.0 keep-alive最佳实践
2017/07/06 Javascript
教你5分钟学会用requirejs(必看篇)
2017/07/25 Javascript
全面介绍vue 全家桶和项目实例
2017/12/27 Javascript
编写React组件项目实践分析
2018/03/04 Javascript
JS删除String里某个字符的方法
2021/01/06 Javascript
vue中实现上传文件给后台实例详解
2019/08/22 Javascript
Angular+ionic实现折叠展开效果的示例代码
2020/07/29 Javascript
利用Python如何生成便签图片详解
2018/07/09 Python
Python设置matplotlib.plot的坐标轴刻度间隔以及刻度范围
2019/06/25 Python
Python将视频或者动态图gif逐帧保存为图片的方法
2019/09/10 Python
Django静态资源部署404问题解决方案
2020/05/11 Python
python使用for...else跳出双层嵌套循环的方法实例
2020/05/17 Python
提高python代码运行效率的一些建议
2020/09/29 Python
球队口号
2014/06/18 职场文书
考试作弊检讨
2015/01/27 职场文书
安全生产先进个人总结
2015/02/15 职场文书
五星级酒店前台接待岗位职责
2015/04/02 职场文书
幼儿园老师工作总结2015
2015/05/22 职场文书
教你如何用Python实现人脸识别(含源代码)
2021/06/23 Python
css3中2D转换之有趣的transform形变效果
2022/02/24 HTML / CSS