「java接口防刷」接口如何防刷

博主:adminadmin 2022-12-12 10:09:09 93

今天给各位分享java接口防刷的知识,其中也会对接口如何防刷进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

javaweb防止表单重复提交的几种解决方案

1.js方法解决:关于js方法解决就是说通过js动态控制提交按钮不能多次点击,或者多次点击不起作用。

方案一:通过设立标识使表单不能重复提交:

var flag=true;    function Sub(){        if(flag){

flag = false;

document.form1.onsubmit();

}

}

方案二:一次点击后使得提交按钮变成不可用

input type="button" value="login" onclick="this.disabled=true;this.form.submit();" /

总的来说,js解决方案是基本可以防止重复点击提交按钮造成的重复提交问题,但是前进后退操作,或者F5刷新页面等问题并不能得到解决。

最重要的一点,前端的代码只能防止不懂js的用户,如果碰到懂得js的编程人员,那js方法就没用了。

2.设置HTTP报头,控制表单缓存,使得所控制的表单不缓存信息,这样用户就无法通过重复点击按钮去重复提交表单。

meta http-equiv="Cache-Control" content="no-cache, must-revalidate"

但是这样做也有局限性,用户在提交页面点击刷新也会造成表单的重复提交。

3.通过PRG设计模式(用来防止F5刷新重复提交表单):

PRG模式通过响应页面Header返回HTTP状态码进行页面跳转替代响应页面跳转过程。具体过程如下:

客户端用POST方法请求服务器端数据变更,服务器对客户端发来的请求进行处理重定向到另一个结果页面上,客户端所有对页面的显示请求都用get方法告知服务器端,这样做,后退再前进或刷新的行为都发出的是get请求,不会对server产生任何数据更改的影响。

但此方法也不能防止所有情况:例如用户多次点击提交按钮;恶意用户避开客户端预防多次提交手段,进行重复提交请求;

以上都说的是在客户端如何防止表单重复提交,下面说一下服务器端有哪些可行的方法。

4.如果是注册或存入数据库的操作,可以通过在数据库中字段设立唯一标识来解决,这样在进行数据库插入操作时,因为每次插入的数据都相同,数据库会拒绝写入。这样也避免了向数据库中写入垃圾数据的情况,同时也解决了表单重复提交问题。

但是这种方法在业务逻辑上感觉是说不过去的,本来该有的逻辑,缺因为数据库该有的设计隐藏了。而且这种方法也有一定的功能局限性,只适用于某系特定的插入操作。

5.session方法:

在struts框架中防止表单重复提交的方法是生成Token存入session,以此判断表单是否是第一次提交。以下给大家解释一下运行流程。

首先客户端请求服务器中的表单,服务器将客户机所请求的表单发给客户机同时发送一个特殊的随机数(Token)作为表单号存在表单的隐藏域中(type=hidden),并且存入服务器端的session中。

在客户端填写完表单内容向服务器提交时,同时也将隐藏域中的表单号发给服务器端,服务器端此时会检测服务器端的表单号是否存在,如果存在,则进行提交操作,并删除此表单号,否则,服务器视为客户机端重复提交表单,不予操作。

此处贴出生成Token的代码(保证随机数的独一无二性):

class Token{    private Token(){}    private static Token instance = new Token();

public Token getinstance(){        return instance;

}

//随机数发生器

public String getToken(){

String token = System.currentTimeMillis() + "" + new Random().nextInt();//获得毫秒数加随机数

try {

MessageDigest md = MessageDigest.getInstance("md5");            byte[] md5 = md.digest(token.getBytes());

BASE64Encoder base = new BASE64Encoder();

base.encode(md5);

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

}

return null;

}

}

要强调的是,利用session方法解决表单重复问题是十分完美的,基本上可以应对各种重复提交问题。

但!是不是之前在客户端防止表单重复提交的种种方法就不使用了呢?

答案是否定的,我们需要多种方法混合使用才能达到最好的效果,也许有人会问,不是说session方法基本可以应对各种重复提交问题了吗?

这里我们所说的达到最好效果指的是,给用户更好地体验,例如用户点击了提交按钮,这时将按钮变为不可用的,用以告诉用户你已经提交内容了,不可重复提交。还有如果无论什么情况都用session防止表单重复提交问题,反而无形的增加了服务器端的负担。

如何设置短信验证码防防刷机制?

还可以,现在在用,会指导设置防刷机制,一般就是增加图形验证码,还有就是进行手机号、发送时间以及IP限制等

如何防止短信接口验证码被恶意点击

普通自开发

发送时间间隔

设置同一个号码重复发送的时间间隔,一般设置为60-120秒。该手段可以在一定程度上防止短信接口被恶意攻击,且对用户体验没有什么伤害。但是不能防止黑客更换手机号进行攻击,防护等级较低。

获取次数限制

限制某个手机号在某个时间段内获取短信验证码次数的上限。采用这种策略时在产品设计过程中,有几点需要注意。

定义上限值。根据业务真实的情况,甚至需要考虑到将来业务的发展定一个合适的上限值,避免因用户无法收到短信验证码而带来的投诉。

定义锁定时间段。可以是24小时,可以是12小时、6小时。需要根据业务情况进行定义。

IP限制

设置单个IP地址某个时间段内最大的发送量。该手段可很好的预防单一IP地址的攻击,但是也有两个很明显的缺点:

对于经常变更IP地址进行攻击的黑客,该手段没有很好的效果。

IP的限制经常会造成误伤。如在一些使用统一无线网的场所,很多用户连接着同一个无线网,这个IP地址就容易很快达到上限,从而造成连接该无线网的用户都无法正常的收到验证码。

图形验证码

在发送短信验证码之前,必须通过通过图形验证码的校验。这种手段相对来说可以防止某些攻击,因此也是目前非常普遍的短信防攻击机制。但是在使用过程中涉及到用户体验问题,不能简单粗暴地套用这一策略。以下几个点值得仔细考虑:

是不是每次获取短信验证码之前都需要用户输入图形验证码,一般来说这样做会极大地影响用户体验,虽然是相对安全,但是用户用着不爽了。

可以给一个安全范围。结合手机号限制、IP限制来考虑,比如同一个手机号当天第3次获取短信验证码的时候,出现图形验证码;比如同一个IP地址当天获取验证码次数超过100次后,出现图形验证码。

加密限制

通过对传向服务器各项参数进行加密,到了服务器再进行解密,同时用token作为唯一性识别验证,在后端对token进行验证,验证通过才能正常将短信发送。该手段可以在保证用户体验的情况下,可以有效防止某些攻击,因此也是目前比较常见的短信防攻击机制。同时也有很明显的缺点:

使用的加解密算法可能会被破解,需要考虑使用破解难度较大的加解密算法。

在算法不被破解的情况下可以有效防止报文攻击,但是无法防止浏览器模拟机式攻击。

以上是几种常见的短信风控策略,在具体的产品设计过程中,可以综合使用。

使用第三方防御

短信防火墙

为了在产品安全和优秀的用户体验之间寻找一个极佳的平衡。新昕科技的产品研发团队结合各种风控策略的优点研发出了一款短信防火墙。 从以下几个方面概括一下:

为保障优秀的用户体验,摈弃了目前影响用户体验最为严重的图形验证码等人机校验程序,做到无感验证。从而达到完美的用户体验。

结合用户的手机号码 、IP地址 、设备指纹三个唯一身份标识设置不同维度的风控策略。将各个维度之间相互配合,达到一个最为合理的风控限制指标。

根据业务情况自动伸缩风控限制,在检测处受攻击时自动加大风控限制力度,在正常是再归回到正常风控标准。

考虑到存在新老客户的区别,特意增加老客户VIP通道,在受到攻击时,风控指标紧缩的情况下,保证老客户通道畅通无阻,从而降低误伤率。

通过以上策略可以有防止黑客通过随意切换手机号及IP地址的方式可以刷取短信。同时加入模拟器检测,以及参数加密等风控策略,有效防止黑客攻击。

可通过风控防火墙控制台,实时观测风控结果,在受到攻击时达到第一时间预警的效果。

如需了解更多请关注新昕科技官网:newxtc.com

短信防火墙

请点击输入图片描述

请点击输入图片描述

短信防火墙

javaweb开发怎么防止机器攻击一直刷短信验证码

设置时间间隔,发送一次短信验证码之后必须隔一段时间后才能继续下一次验证,在这个基础上,如果还有多次发送的,就开启图灵验证码,必须输入正确图片的内容,才能继续发送短信验证码

java接口怎么防止被刷

为什么会有人要刷接口?

1、牟利

黄牛在 12306 网上抢票再倒卖。

2、恶意攻击竞争对手

如短信接口被请求一次,会触发几分钱的运营商费用,当量级大了也很可观。

3、压测

用 apache bench 做压力测试。

4、当程序员无聊的时候

什么是刷接口的"刷"字?

1、次数

2、频率

频繁,可能 1 秒上千次

3、用户身份难以识别

可能会在刷的过程中随时换浏览器或者 ip

判断接口是否是恶意?

根据用户粒度,如果该用户符合上面提到的“刷”的概念,就是恶意的。

用户粒度如何划分?

1、当前网页

优点:无

缺点:没有任何意义,一刷新页面用户的身份就变了

2、session

优点:伪造成本一般(可以理解成一个浏览器对应了一个用户)

缺点:当用户手动清除 cookie 的时候即失效

3、ip

优点:伪造成本高

缺点:要考虑一个公司、一个小区的人一般会共享一个 ip,所以适当的要放宽对单一 ip 的请求限制

ip 信息是存在请求头里的,而 https 对请求本身做了加密,可以防止 ip 信息被伪造或篡改。所以推荐服务器采用 https 传输。

当知道接口是恶意请求时,我们该怎么做?

一、直接拒绝访问

优点:简单粗暴

缺点:简单粗暴

二、返回“操作频繁”的错误提示

优点:提示友好

缺点:会把确实是操作比较频繁的真实用户拦截

三、验证码

1、图形

2、滑块

3、找不同

优点:精准识别请求是真人还是机器发出的,二次筛选出真正的用户

缺点:不够人性化,用户操作时间长、体验差

4、限制ip

客户端请求的时候 , 把ip记录下来,每次访问这个ip访问次数+1,如果查过制定次数,把这个ip拉黑

实例:

安全问题是长期的和攻击者斗智斗勇的问题,没有一劳永逸的解决方案,不断交锋,不断成长

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

前几天项目上需要对一个正常登陆接口,以及忘记密码的接口进行防爆破处理,这里我用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.

java接口防刷的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于接口如何防刷、java接口防刷的信息别忘了在本站进行查找喔。

The End

发布于:2022-12-12,除非注明,否则均为首码项目网原创文章,转载请注明出处。