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 相关文章推荐
攻克CakePHP系列一 连接MySQL数据库
Oct 22 PHP
PHP企业级应用之常见缓存技术篇
Jan 27 PHP
解析php中mysql_connect与mysql_pconncet的区别详解
May 15 PHP
php MessagePack介绍
Oct 06 PHP
php多种形式发送邮件(mail qmail邮件系统 phpmailer类)
Jan 22 PHP
php实现图片添加描边字和马赛克的方法
Dec 10 PHP
分享十款最出色的PHP安全开发库中文详细介绍
Mar 22 PHP
PHP+JS三级菜单联动菜单实现方法
Feb 24 PHP
PHP调用存储过程返回值不一致问题的解决方法分析
Apr 26 PHP
PHP给前端返回一个JSON对象的实例讲解
May 31 PHP
详解如何实现Laravel的服务容器的方法示例
Apr 15 PHP
thinkphp5.1框架容器与依赖注入实例分析
Jul 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
php中3种方法删除字符串中间的空格
2014/03/10 PHP
php正则匹配文章中的远程图片地址并下载图片至本地
2015/09/29 PHP
基于PHP生成简单的验证码
2016/06/01 PHP
yii插入数据库防并发的简单代码
2017/05/27 PHP
PHP架构及原理知识点详解
2019/12/22 PHP
Aster vs Newbee BO3 第二场2.18
2021/03/10 DOTA
javascript prototype原型操作笔记
2009/12/07 Javascript
HTML node相关的一些资料整理
2010/01/01 Javascript
基于Jquery的淡入淡出的特效基础练习
2010/12/13 Javascript
Draggable Elements 元素拖拽功能实现代码
2011/03/30 Javascript
javascript 基础篇4 window对象,DOM
2012/03/14 Javascript
Node.js实现批量去除BOM文件头
2014/12/20 Javascript
关于Node.js的events.EventEmitter用法介绍
2017/04/01 Javascript
微信小程序与php 实现微信支付的简单实例
2017/06/23 Javascript
iview Upload组件多个文件上传的示例代码
2018/09/30 Javascript
D3.js 实现带伸缩时间轴拓扑图的示例代码
2020/01/20 Javascript
[02:25]DOTA2英雄基础教程 熊战士
2014/01/03 DOTA
跟老齐学Python之玩转字符串(1)
2014/09/14 Python
python中管道用法入门实例
2015/06/04 Python
详细解读tornado协程(coroutine)原理
2018/01/15 Python
python随机取list中的元素方法
2018/04/08 Python
python学习——内置函数、数据结构、标准库的技巧(推荐)
2019/04/18 Python
Python3多目标赋值及共享引用注意事项
2019/05/27 Python
详解PyCharm+QTDesigner+PyUIC使用教程
2019/06/13 Python
python求最大值最小值方法总结
2019/06/25 Python
使用Python中的reduce()函数求积的实例
2019/06/28 Python
Python初学者常见错误详解
2019/07/02 Python
Python实现数值积分方式
2019/11/20 Python
Python 实现OpenCV格式和PIL.Image格式互转
2020/01/09 Python
解决Python图形界面中设置尺寸的问题
2020/03/05 Python
adidas旗下高尔夫装备供应商:TaylorMade Golf(泰勒梅高尔夫)
2016/08/28 全球购物
美国睫毛、眉毛精华液领导品牌:RevitaLash Cosmetics
2018/03/26 全球购物
预备党员党校学习自我评价分享
2013/11/12 职场文书
大学生毕业的自我评价分享
2014/01/02 职场文书
文明礼仪演讲稿
2014/05/12 职场文书
使用Djongo模块在Django中使用MongoDB数据库
2021/06/20 Python