好得很程序员自学网
  • 首页
  • 后端语言
    • C#
    • PHP
    • Python
    • java
    • Golang
    • ASP.NET
  • 前端开发
    • Angular
    • react框架
    • LayUi开发
    • javascript
    • HTML与HTML5
    • CSS与CSS3
    • jQuery
    • Bootstrap
    • NodeJS
    • Vue与小程序技术
    • Photoshop
  • 数据库技术
    • MSSQL
    • MYSQL
    • Redis
    • MongoDB
    • Oracle
    • PostgreSQL
    • Sqlite
    • 数据库基础
    • 数据库排错
  • CMS系统
    • HDHCMS
    • WordPress
    • Dedecms
    • PhpCms
    • 帝国CMS
    • ThinkPHP
    • Discuz
    • ZBlog
    • ECSHOP
  • 高手进阶
    • Android技术
    • 正则表达式
    • 数据结构与算法
  • 系统运维
    • Windows
    • apache
    • 服务器排错
    • 网站安全
    • nginx
    • linux系统
    • MacOS
  • 学习教程
    • 前端脚本教程
    • HTML与CSS 教程
    • 脚本语言教程
    • 数据库教程
    • 应用系统教程
  • 新技术
  • 编程导航
    • 区块链
    • IT资讯
    • 设计灵感
    • 建站资源
    • 开发团队
    • 程序社区
    • 图标图库
    • 图形动效
    • IDE环境
    • 在线工具
    • 调试测试
    • Node开发
    • 游戏框架
    • CSS库
    • Jquery插件
    • Js插件
    • Web框架
    • 移动端框架
    • 模块管理
    • 开发社区
    • 在线课堂
    • 框架类库
    • 项目托管
    • 云服务

当前位置:首页>后端语言>PHP
<tfoot draggable='sEl'></tfoot>

phpredis防刷 php防cc

很多站长朋友们都不太清楚phpredis防刷,今天小编就来给大家整理phpredis防刷,希望对各位有所帮助,具体内容如下:

本文目录一览: 1、 php在程序结束后释放redis缓存 2、 订单超时,活动过期解决方案:php监听redis键重复触发引发事件 3、 后台登陆防刷、防爆破以及正常的登录校验 4、 php redis如何使用 php在程序结束后释放redis缓存

php在程序结束后释放redis缓存 :PHP的unset()函数用来清除、销毁变量,不用的变量,我们可以用unset()将它销毁。但是某些时候,用unset()却无法达到销毁变量占用的内存!

订单超时,活动过期解决方案:php监听redis键重复触发引发事件

订单超时,活动过期解决方案:php监听redis键重复触发引发事件

Redis的2.8.0版本之后可用,键空间消息(Redis Keyspace Notifications),配合2.0.0版本之后的SUBSCRIBE 可以完成这个定时任务的操作了,定时的单位是秒。

1.我们先订阅频道称为 redisChat

2.现在,我们重新开启个redis客户端,然后在同一个频道redisChat发布消息,订阅者可以接收到消息。

接收到的消息如下:

3.Key过期事件的Redis配置

需要这里配置notify-keyspace-events的参数为“EX” .X代表了过期事件。notify-keyspace-events “Ex”保存配置后,重启Redis的服务,使配置生效。

PHP Redis实现订阅键空间通知

redis实例化类:

redis.class.php

1个

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18岁

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

//遇到类别重复的报错,所有叫Redis2

classRedis2  

{

    private$redis;

    publicfunction__construct($host= '127.0.0.1', $port= 6379)

    {

        $this->redis = newRedis();

        $this->redis->connect($host, $port);

    }

    publicfunctionsetex($key, $time, $val)

    {

        return$this->redis->setex($key, $time, $val);

    }

    publicfunctionset($key, $val)

    {

        return$this->redis->set($key, $val);

    }

    publicfunctionget($key)

    {

        return$this->redis->get($key);

    }

    publicfunctionexpire($key= null, $time= 0)

    {

        return$this->redis->expire($key, $time);

    }

    publicfunctionpsubscribe($patterns= array(), $callback)

    {

        $this->redis->psubscribe($patterns, $callback);

    }

    publicfunctionsetOption()

    {

        $this->redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);

    }

}

过期事件的订阅:

psubscribe.php

1个

2

3

4

5

6

7

8

9

10

11

12

13

14

15

require_once'./Redis.class.php';

$redis= new\Redis2();

// 解决Redis客户端订阅时候超时情况

$redis->setOption();

$redis->psubscribe(array('__keyevent@0__:expired'), 'keyCallback');

// 回调函数,这里写处理逻辑

functionkeyCallback($redis, $pattern, $chan, $msg)

{

    echo"Pattern: $pattern\n";

    echo"Channel: $chan\n";

    echo"Payl

    oad: $msg\n\n";

    //keyCallback为订阅事件后的回调函数,这里写业务处理逻辑,

    //比如前面提到的商品不支付自动撤单,这里就可以根据订单id,来实现自动撤单

}

设置过期事件:

index.php

1个

2

3

4

require_once'./Redis.class.php';

$redis= new\Redis2();

$order_id= 123;

$redis->setex('order_id',10,$order_id);

先用命令行模式执行 psubscribe.php

在浏览器访问 index.php

效果如下:

后台登陆防刷、防爆破以及正常的登录校验

前几天项目上需要对一个正常登陆接口,以及忘记密码的接口进行防爆破处理,这里我用nginx,redis,以及前端的一些简单的图形拖动来做一个简单的安全机制,可能有不完善的地方,大家可以提出来意见。

其实一个接口是无法完全避免接口爆破的,区分人和机器或许可以使用谷歌的图片验证机制,但是我们一般简单项目没必要做那么复杂的,只需要确保不正常的访问频率不会爆破出我们的用户信息,以及让我们机器的处理流量保存在可控范围即可。

验证码只能60s获取一次 并且3小时内只能获取三次,超过次数提升获取频繁,稍后再试。

正常登录1小时内失败6次账号自动锁定,1小时之后自动解锁。

获取验证码无论输入的账号存在不存在均显示发送成功,但是实际不存在的账号不会正常发送。

4.登录失败,账号不存在密码错误不再提示账号不存在等等,而是统一显示账号或密码错误。5.忘记密码前端部分增加滑动校验,60倒计时无法点击发送验证码。前后端共同校验。6.技术限制系统此接口的访问频率。

前端部分可以在这个地址看看这几个简单的组件,这次我们就使用最简单的,滑动拖动即可。

<drag-verify

              ref="dragVerify"

              :width="width"

              :height="height"

              text="请按住滑块拖动"

              successText="验证通过"

              :isPassing.sync="isPassing"

              background="#ccc"

              completedBg="rgb(105, 231, 251)"

              handlerIcon="el-icon-d-arrow-right"

              successIcon="el-icon-circle-check"

              @passcallback="passcallback"

          >

          </drag-verify>

用户滑动之后需要加上60s倒计时,这块我们使用定时器实现即可,以及邮箱和手机号的正确性校验,不正确则弹窗提示。

this.countDown = 60;

      timer = setInterval(() => {

        if (this.countDown - 1 >= 0) {

          this.countDown -= 1;

        } else {

          clearInterval(timer);

          timer = null;

        }

      }, 1000);

<el-button disabled type="text" v-show="time > 0">

{{ time > 0 ? `${time}` : "" }} s之后重试</el-button>

验证邮箱手机号可以使用正则校验进行。

mobileReg = /^1\d{10}$/;

      emailReg = /^([A-Za-z0-9_\-\.\u4e00-\u9fa5])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,8})$/;

前端大体思路就是,进行滑块验证,拖到右边之后,60s之内无法操作,60s到期之后自动复原,

显示倒计时时间。这个只能防止用户在页面上多次点击,造成一个验证的假象,如果直接对后端接口爆破,则无法避免。

这是大概的流程图,图中还有些细节问题下面慢慢讲解。

这块本来我想用java或者kotlin写,但是历史项目用go写的,重写的话还有其他一些改动,所以继续使用golang完成这部分逻辑。

先定义一个结构体,然后我们来分析下需要哪些字段来实现我们的业务。

type CommonLogin struct {

    CreateTime time.Time

    LastTime  time.Time

    Times      uint8

}

// 登录的前置校验

func beforeCommonLoginValid(key string, r *redis.Client, field string) (bool, error) {

    // redis中是否存在账号

    result, err := r.HExists(field, key).Result()

    if err != nil {

            fmt.Printf("从redis中获取用户账户失败,账户为: %s", key)

            return false, err

    }

    if result {

            login := CommonLogin{}

            // 存在账号 说明之前登录失败过 且自从上次失败未登录成功过

            commonLogin, err := r.HGet(field, key).Result()

            if err != nil {

                    return false, err

            }

            json.Unmarshal([]byte(commonLogin), login)

            if login.Times < 6 {

                    return true, nil

            }

            // 是否在1小时内失败了6次

            if login.Times >= 6 {

                    // 否

                    if time.Now().Sub(login.CreateTime) > time.Hour*1 {

                            // 连续输错6次时长大于1小时 解锁

                            r.HDel(field, key)

                            return true, nil

                    } else {

                            fmt.Printf("用户%s于1小时之内连续登录失败6次,账号锁定,1小时后重试。", key)

                            return false, nil

                    }

            }

    }

    // redis中不存在重试记录

    return true, nil

}

在所有的登录判断的出口,调用此方法即可,例如用户名密码错误,acl校验未通过等等。

其实原理差不多,唯一的区别就是多了一个获取验证码时间间隔校验。

func beforeForgotPasswordValid(key string, r *redis.Client, field string) (bool, error) {

    // redis中是否存在账号

    result, err := r.HExists(field, key).Result()

    if err != nil {

            fmt.Printf("从redis中获取用户账户失败,账户为: %s", key)

            return false, err

    }

    login := CommonLogin{}

    // 账号存在

    if result {

            commonLogin, err := r.HGet(field, key).Result()

            if err != nil {

                    return false, err

            }

            json.Unmarshal([]byte(commonLogin), login)

            // 获取验证码间隔时长不能小于60s

            if time.Now().Sub(login.LastTime) < time.Second*60 {

                    fmt.Printf("用户获取验证码间隔小于60s")

                    return false, nil

            }

            if login.Times < 3 {

                    return true, nil

            }

            // 是否在1小时内获取了3次

            if login.Times >= 3 {

                    // 否

                    if time.Now().Sub(login.CreateTime) > time.Hour*3 {

                            // 连续输错6次时长大于1小时 解锁

                            r.HDel(field, key)

                            return true, nil

                    } else {

                            fmt.Printf("用户%s于3小时之内连续获取验证码3次,账号锁定,3小时后重试。", key)

                            return false, nil

                    }

            }

    }

    return true, nil

}

// 更新获取验证码的时间

func afterForgotPasswordValid(key string, r *redis.Client, field string) {

    login := CommonLogin{}

    commonLogin, _ := r.HGet(field, key).Result()

    json.Unmarshal([]byte(commonLogin), login)

    // 验证码发送成功

    result, _ := r.HExists(field, key).Result()

    if result {

            login.Times = login.Times + 1

            login.LastTime = time.Now()

            data, _ := json.Marshal(login)

            r.HSet(field, key, data)

    } else {

            login.Times = 1

            login.LastTime = time.Now()

            login.CreateTime = login.LastTime

            data, _ := json.Marshal(login)

            r.HSet(field, key, data)

    }

}

nginx是一个非常强大的中间价,在安全方面,我们可以用它来限制来自于同一机器的访问频率,可以做黑名单功能等等,当然有人会说ip代{过}{滤}理池之类的,我们此次演示的只是简单demo,恶意攻击当然需要专业防护了。

具体google一下,看这两篇官方文档。

具体的配置其实很简单了。

限制远程同ip访问频率。

limit_req_zone$binary_remote_addrzone=perip:10mrate=1r/s;

$binary_remote_addr 表示通过remote

addr这个标识来做限制,“binary ”的目的是缩写内存占用量,是限制同一客户端ip地址

zone=one:10m表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息

rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,还可以有比如30r/m的

location ^~ /api/xxx {

        limit_req zone=perip nodelay;

        limit_req_status 503;

        proxy_pass http://正确地址;

    }

上面配置意思就是超过频率返回503,服务不可用。

使用jmeter进行压力测试:1s 10个请求,我们预期只有1个请求成功,其他的返回503.

php redis如何使用

开始在

PHP

中使用

Redis

前,要确保已经安装了

redis

服务及

PHP

redis

驱动,且你的机器上能正常使用

PHP。

PHP安装redis扩展

/usr/local/php/bin/phpize

#php安装后的路径

./configure

--with-php-config=/usr/local/php/bin/php-config

make

make

install

修改php.ini文件

vi

/usr/local/php/lib/php.ini

增加如下内容:

extension_dir

=

"/usr/local/php/lib/php/extensions/no-debug-zts-20090626"

extension=redis.so

安装完成后重启php-fpm

或

apache。查看phpinfo信息,就能看到redis扩展。

连接到

redis

服务

<?php

//连接本地的

Redis

服务

$redis

=

new

Redis();

$redis->connect('127.0.0.1',

6379);

echo

"Connection

to

server

sucessfully";

//查看服务是否运行

echo

"Server

is

running:

"

.

$redis->ping();

?>

执行脚本,输出结果为:

Connection

to

server

sucessfully

Server

is

running:

PONG

Redis

PHP

String(字符串)

实例

<?php

//连接本地的

Redis

服务

$redis

=

new

Redis();

$redis->connect('127.0.0.1',

6379);

echo

"Connection

to

server

sucessfully";

//设置

redis

字符串数据

$redis->set("tutorial-name",

"Redis

tutorial");

//

获取存储的数据并输出

echo

"Stored

string

in

redis::

"

.

jedis.get("tutorial-name");

?>

执行脚本,输出结果为:

Connection

to

server

sucessfully

Stored

string

in

redis::

Redis

tutorial

Redis

PHP

List(列表)

实例

<?php

//连接本地的

Redis

服务

$redis

=

new

Redis();

$redis->connect('127.0.0.1',

6379);

echo

"Connection

to

server

sucessfully";

//存储数据到列表中

$redis->lpush("tutorial-list",

"Redis");

$redis->lpush("tutorial-list",

"Mongodb");

$redis->lpush("tutorial-list",

"Mysql");

//

获取存储的数据并输出

$arList

=

$redis->lrange("tutorial-list",

,5);

echo

"Stored

string

in

redis::

"

print_r($arList);

?>

执行脚本,输出结果为:

Connection

to

server

sucessfully

Stored

string

in

redis::

Redis

Mongodb

Mysql

Redis

PHP

Keys

实例

<?php

//连接本地的

Redis

服务

$redis

=

new

Redis();

$redis->connect('127.0.0.1',

6379);

echo

"Connection

to

server

sucessfully";

//

获取数据并输出

$arList

=

$redis->keys("*");

echo

"Stored

keys

in

redis::

"

print_r($arList);

?>

执行脚本,输出结果为:

Connection

to

server

sucessfully

Stored

string

in

redis::

tutorial-name

tutorial-list

关于phpredis防刷的介绍到此就结束了,不知道本篇文章是否对您有帮助呢?如果你还想了解更多此类信息,记得收藏关注本站,我们会不定期更新哦。

查看更多关于phpredis防刷 php防cc的详细内容...

声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did194891
更新时间:2023-04-26   阅读:24次

上一篇: php加密下载地址 php代码加密软件

下一篇:php握手传输数据 php传输数据的方式

最新资料更新

  • 1.韩顺平php视频教程下载 韩顺平oracle视频
  • 2.php网络通信 php通信协议
  • 3.修改文件限制php php修改上传文件大小
  • 4.php正则获取图片 php使用正则表达式
  • 5.php文件工具类 php文件处理
  • 6.php协议input php协议,json
  • 7.php实现权限分配 php权限设计
  • 8.PHP中嵌入script php嵌入html有哪几种方法
  • 9.token验证php Token验证失败异地登陆什么意思
  • 10.php会做流控吗 php流程控制
  • 11.php的sql累加 sql实现累加
  • 12.中南php哪家好 中南cp
  • 13.zendphp调试 调试教程
  • 14.php手机qr php手机编程软件
  • 15.php下面有哪些技术 php运用的技术php开发有哪些实用的技术
  • 16.php框架开发教程 php系统开发框架
  • 17.phpml源码安装 下载了个php源码包,怎么使用
  • 18.php受不受欢迎 php无法接收post
  • 19.如何阅读php源码 php在线源码获取
  • 20.射洪php招聘 射洪平台公司招聘

CopyRight:2016-{hedonghua:year}{hedonghua:sitegs} 备案ICP:湘ICP备09009000号-16 {hedonghua:sitejym}
本站资讯不构成任何建议,仅限于个人分享,参考须谨慎!
本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任。
本网站刊载的所有内容(包括但不仅限文字、图片、LOGO、音频、视频、软件、程序等)版权归原作者所有。任何单位或个人认为本网站中的内容可能涉嫌侵犯其知识产权或存在不实内容时,请及时通知本站,予以删除。

网站内容来源于网络分享,如有侵权发邮箱到:kenbest@126.com,收到邮件我们会即时下线处理。
网站框架支持:HDHCMS   51LA统计 百度统计
Copyright © 2018-2025 「好得很程序员自学网」
[ SiteMap ]