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扩展ZF――Validate扩展
Jan 10 PHP
php操作sqlserver关于时间日期读取的小小见解
Nov 29 PHP
PHP读取ACCESS数据到MYSQL的代码
May 11 PHP
php数组函数序列 之shuffle()和array_rand() 随机函数使用介绍
Oct 29 PHP
php定时计划任务的实现方法详解
Jun 06 PHP
ThinkPHP页面跳转success与error方法概述
Jun 25 PHP
Laravel 5框架学习之数据库迁移(Migrations)
Apr 08 PHP
PHP实现链式操作的核心思想
Jun 23 PHP
PHP序列化/对象注入漏洞分析
Apr 18 PHP
php处理多图上传压缩代码功能
Jun 13 PHP
Laravel5.1 框架Request请求操作常见用法实例分析
Jan 04 PHP
php面向对象基础详解【星际争霸游戏案例】
Jan 23 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
日本因肺炎疫情影响,这几部动漫推延播放!
2020/03/03 日漫
PHP n个不重复的随机数生成代码
2009/06/23 PHP
浅谈json_encode用法
2015/03/05 PHP
微信公众平台DEMO(PHP)
2016/05/04 PHP
PHP常用的三种设计模式汇总
2016/08/28 PHP
js获取html文件的思路及示例
2013/09/17 Javascript
javascript陷阱 一不小心你就中招了(字符运算)
2013/11/10 Javascript
artDialog+plupload实现多文件上传
2016/07/19 Javascript
js两种拼接字符串的简单方法(必看)
2016/09/02 Javascript
ReactNative页面跳转实例代码
2016/09/27 Javascript
js实现简单的计算器功能
2017/01/16 Javascript
利用js的闭包原理做对象封装及调用方法
2017/04/07 Javascript
JavaScript基于面向对象实现的猜拳游戏
2018/01/03 Javascript
Vue2 模板template的四种写法总结
2018/02/23 Javascript
使用nvm和nrm优化node.js工作流的方法
2019/01/17 Javascript
解决vue中使用proxy配置不同端口和ip接口问题
2019/08/14 Javascript
haskell实现多线程服务器实例代码
2013/11/26 Python
Tensorflow 训练自己的数据集将数据直接导入到内存
2018/06/19 Python
Python实现监控键盘鼠标操作示例【基于pyHook与pythoncom模块】
2018/09/04 Python
使用Python快速制作可视化报表的方法
2019/02/03 Python
Python使用线程来接收串口数据的示例
2019/07/02 Python
python文字和unicode/ascll相互转换函数及简单加密解密实现代码
2019/08/12 Python
Python爬虫 urllib2的使用方法详解
2019/09/23 Python
keras 模型参数,模型保存,中间结果输出操作
2020/07/06 Python
vscode+PyQt5安装详解步骤
2020/08/12 Python
css3中flex布局宽度不生效的解决
2020/12/09 HTML / CSS
使用HTML5的File实现base64和图片的互转
2013/08/01 HTML / CSS
瑞典手机壳品牌:Richmond & Finch
2018/04/28 全球购物
社区服务活动总结
2014/05/07 职场文书
教师廉洁自律承诺书
2014/05/26 职场文书
签约仪式策划方案
2014/06/02 职场文书
学习型党组织心得体会
2014/09/12 职场文书
2014学习优秀共产党员先进事迹材料思想汇报
2014/09/14 职场文书
乡镇党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
爱的教育观后感
2015/06/17 职场文书
PyTorch 如何检查模型梯度是否可导
2021/06/05 Python