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 相关文章推荐
MySql中正则表达式的使用方法描述
Jul 30 PHP
PHP 获取客户端真实IP地址多种方法小结
May 15 PHP
php Rename 更改文件、文件夹名称
May 24 PHP
浅谈apache和nginx的rewrite的区别
Feb 22 PHP
9段PHP实用功能的代码推荐
Oct 14 PHP
php获取CSS文件中图片地址并下载到本地的方法
Dec 02 PHP
PHP实现WebService的简单示例和实现步骤
Mar 27 PHP
PHP的Yii框架的常用日志操作总结
Dec 08 PHP
PHP程序员的技术成长规划
Mar 25 PHP
PHP简单检测网址是否能够正常打开的方法
Sep 04 PHP
php检测mysql表是否存在的方法小结
Jul 20 PHP
PHP数据库操作三:redis用法分析
Aug 16 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 判断常量,变量和函数是否存在
2009/04/26 PHP
PHP中去掉字符串首尾空格的方法
2012/05/19 PHP
PHP分页详细讲解(有实例)
2013/10/30 PHP
PHP 读取和编写 XML
2014/11/19 PHP
php遍历目录方法小结
2015/03/10 PHP
PHP实现的简单路由和类自动加载功能
2018/03/13 PHP
jquery 可排列的表实现代码
2009/11/13 Javascript
新老版本juqery获取radio对象的方法
2010/03/01 Javascript
javascript奇异的arguments分析
2010/10/20 Javascript
jQuery LigerUI 使用教程入门篇
2012/01/18 Javascript
分享28款免费实用的 JQuery 图片和内容滑块插件
2014/12/15 Javascript
浅析nodejs实现Websocket的数据接收与发送
2015/11/19 NodeJs
JS函数arguments数组获得实际传参数个数的实现方法
2016/05/28 Javascript
利用Vue.js框架实现火车票查询系统(附源码)
2017/02/27 Javascript
JavaScript中offsetWidth的bug及解决方法
2017/05/17 Javascript
vue+ElementUI实现订单页动态添加产品数据效果实例代码
2017/07/13 Javascript
IntelliJ IDEA 安装vue开发插件的方法
2017/11/21 Javascript
vue iview实现动态路由和权限验证功能
2018/04/17 Javascript
解决angularjs中同步执行http请求的方法
2018/08/13 Javascript
Node.js 进程平滑离场剖析小结
2019/01/24 Javascript
原生JS实现音乐播放器的示例代码
2021/02/25 Javascript
[49:08]Secret vs VP 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Python实现读取目录所有文件的文件名并保存到txt文件代码
2014/11/22 Python
详解Swift中属性的声明与作用
2016/06/30 Python
windows下 兼容Python2和Python3的解决方法
2018/12/05 Python
python3让print输出不换行的方法
2020/08/24 Python
西尔斯百货官网:Sears
2016/09/06 全球购物
美国最大的电子宠物训练产品制造商:PetSafe
2018/10/12 全球购物
Hanro官网:奢华男士和女士内衣、睡衣和家居服
2018/10/25 全球购物
Footshop罗马尼亚:最好的运动鞋选择
2019/09/10 全球购物
老总助理工作岗位职责
2014/02/06 职场文书
上党课的心得体会
2014/09/02 职场文书
法人授权委托书
2014/09/16 职场文书
项目负责人岗位职责
2015/02/15 职场文书
入党后的感想
2015/08/10 职场文书
为什么RedisCluster设计成16384个槽
2021/09/25 Redis