从构建分布式秒杀系统聊聊验证码 给大家推荐8个SpringBoot精选项目

前言

为了拦截大部分请求,秒杀案例前端引入了验证码。淘宝上很多人吐槽,等输入完秒杀活动结束了,对,结束了...... 当然了,验证码的真正作用是,有效拦截刷单操作,让羊毛党空手而归。

验证码

那么到底什么是验证码呢?验证码作为一种人机识别手段,其终极目的,就是区分正常人和机器的操作。我们常见的互联网注册、登录、发帖、领优惠券、投票等等应用场景,都有被机器刷造成各类损失的风险。

目前常见的验证码形式多为图片验证码,即数字、字母、文字、图片物体等形式的传统字符验证码。这类验证码看似简单易操作,但实际用户体验较差(参见12306网站),且随着OCR技术和打码平台的利用,图片比较容易被破解,被破解之后就形同虚设。

这里我们使用腾讯的智能人机安全验证码,告别传统验证码的单点防御,十道安全栅栏打造立体全面的安全验证,将黑产拒之门外。

场景

下面我们来瞅瞅验证码轻松解决了那些场景安全问题:

  • 登录注册,为你防护撞库攻击、阻止注册机批量注册
  • 活动秒杀,有效拦截刷单操作,让羊毛党空手而归
  • 点赞发帖,有效解决广告屠版、恶意灌水、刷票问题
  • 数据保护,防止自动机、爬虫盗取网页内容和数据

申请

申请地址:https://007.qq.com/product.html

在线体验:https://007.qq.com/online.html

只要一个QQ就可以免费申请,对于一般的企业OA系统或者个人博客网站,验证码免费套餐足够了已经,具备以下特点:

  • 2000次/小时安全防护
  • 支持免验证+分级验证
  • 三分钟快速接入
  • 全功能配置后台
  • 支持HTTPS
  • 阈值内流量无广告

2000次/小时的安全防护,一般很少达到如此效果,当然了即时超出阈值,顶多也就是多个广告而已。

接入

快读接入:https://007.qq.com/quick-start.html

接入与帮助提供了多种客户端和服务端的接入案例,这里我们使用我们秒杀案例中最熟悉的Java语言来接入。

前端

引入JS:

 <script src="https://ssl.captcha.qq.com/TCaptcha.js"></script>

页面元素:

<!--点击此元素会自动激活验证码,不一定是button,其他标签也可以-->
<!--id : 元素的id(必须)-->
<!--data-appid : AppID(必须)-->
<!--data-cbfn : 回调函数名(必须)--> <!--data-biz-state : 业务自定义透传参数(可选)--> <button id="TencentCaptcha" data-appid="*********" data-cbfn="callback">验证</button>

JS回调:

<script type="text/javascript">
    window.callback = function(res){ console.log(res) // res(未通过验证)= {ret: 1, ticket: null} // res(验证成功) = {ret: 0, ticket: "String", randstr: "String"} if(res.ret === 0){ startSeckill(res) } } //后台验证ticket,并进入秒杀队列 function startSeckill(res){ $.ajax({ url : "startSeckill", type : 'post', data : {'ticket' : res.ticket,'randstr':res.randstr}, success : function(result) { //验证是否通过,提示用户 } }); } </script>

后端

@Api(tags = "秒杀商品")
@RestController
@RequestMapping("/seckillPage")
public class SeckillPageController { @Autowired private ActiveMQSender activeMQSender; //自定义工具类 @Autowired private HttpClient httpClient; //这里自行配置参数 @Value("${qq.captcha.url}") private String url; @Value("${qq.captcha.aid}") private String aid; @Value("${qq.captcha.AppSecretKey}") private String appSecretKey; @RequestMapping("/startSeckill") public Result startSeckill(String ticket,String randstr,HttpServletRequest request) { HttpMethod method =HttpMethod.POST; MultiValueMap<String, String> params= new LinkedMultiValueMap<String, String>(); params.add("aid", aid); params.add("AppSecretKey", appSecretKey); params.add("Ticket", ticket); params.add("Randstr", randstr); params.add("UserIP", IPUtils.getIpAddr(request)); String msg = httpClient.client(url,method,params); /** * response: 1:验证成功,0:验证失败,100:AppSecretKey参数校验错误[required] * evil_level:[0,100],恶意等级[optional] * err_msg:验证错误信息[optional] */ //{"response":"1","evil_level":"0","err_msg":"OK"} JSONObject json = JSONObject.parseObject(msg); String response = (String) json.get("response"); if("1".equals(response)){ //进入队列、假数据而已 Destination destination = new ActiveMQQueue("seckill.queue"); activeMQSender.sendChannelMess(destination,1000+";"+1); return Result.ok(); }else{ return Result.error("验证失败"); } } } 

自定义请求工具类 HttpClient:

@Service
public class HttpClient { public String client(String url, HttpMethod method, MultiValueMap<String, String> params){ RestTemplate client = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); // 请勿轻易改变此提交方式,大部分的情况下,提交方式都是表单提交 headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers); // 执行HTTP请求 ResponseEntity<String> response = client.exchange(url, HttpMethod.POST, requestEntity, String.class); return response.getBody(); } }

获取IP地址工具类 IPUtils :

/**
 * IP地址
 */
public class IPUtils { private static Logger logger = LoggerFactory.getLogger(IPUtils.class); /** * 获取IP地址 * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址 * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址 */ public static String getIpAddr(HttpServletRequest request) { String ip = null; try { ip = request.getHeader("x-forwarded-for"); if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } } catch (Exception e) { logger.error("IPUtils ERROR ", e); } // 使用代理,则获取第一个IP地址 if (StringUtils.isEmpty(ip) && ip.length() > 15) { if (ip.indexOf(",") > 0) { ip = ip.substring(0, ip.indexOf(",")); } } return ip; } }

案例效果图

启动项目访问:http://localhost:8080/seckill/1000.shtml

定制接入

在系统登录的时候,我们需要先校验用户名以及密码,然后调用验证码操作,这里就需要我们定制接入了。

<!-- 项目中使用了Vue -->
<div class="log_btn" @click="login" >登录</div>
login: function () {
    //这里校验用户名以及密码 // 直接生成一个验证码对象 var captcha = new TencentCaptcha('2001344788', function(res) { if(res.ret === 0){//回调成功 var data = {'username':username,'password':password,'ticket':res.ticket,'randstr':res.randstr} $.ajax({ type: "POST", url: "sys/loginCaptcha", data: data, dataType: "json", success: function(result){ //校验是否成功 } }); } }); captcha.show(); // 显示验证码 },

后台监控

腾讯后台还提供了简单实用的数据监控,如下:

小结

总体来说,系统接入人机验证码还是很方便的,并没有技术难点,难点已经被提供商封装,我们只需要简单的调用即可。

秒杀案例:https://gitee.com/52itstyle/spring-boot-seckill

演示案例(点击生成按钮):http://jichou.52itstyle.com

 

 

 

项目案例

项目一:支付服务

简介:支付服务:支付宝、微信、银联详细 代码案例,目前已经1900+Star。十分钟让你快速搭建一个支付服务,内附各种教程。

项目地址:https://gitee.com/52itstyle/spring-boot-pay

项目二:秒杀案例

简介:从0到1构建分布式秒杀系统,脱离案例讲架构都是耍流氓,码云GVP项目。这个是自5月以来最上心的一个项目,尽管只是一个案例,但是从中也学到了不少知识。

项目地址:https://gitee.com/52itstyle/spring-boot-seckill

项目三:邮件服务

简介:邮件发送服务,文本,附件,模板,队列,多线程,定时任务实现多种功能。

项目地址:https://gitee.com/52itstyle/spring-boot-mail

项目四:全文搜索服务

简介:ES全文搜索引擎,基于Elasticsearch构建网站日志处理系统,通过数据同步工具等一些列开源组件来快速构建一个日志处理系统,项目雏形初步成型中。

项目地址:https://gitee.com/52itstyle/spring-boot-elasticsearch

项目五:任务管理系统

简介:基于spring-boot+quartz的CRUD任务管理系统 。

项目地址:https://gitee.com/52itstyle/spring-boot-quartz

项目六:在线文档管理系统

简介:spring-boot-doc是一款针对IT团队开发的简单好用的文档管理系统。

项目地址:https://gitee.com/52itstyle/spring-boot-doc

项目七:分布式文件系统

简介:没什么好介绍的,集成了Fastdfs而已。

项目地址:https://gitee.com/52itstyle/spring-boot-fastdfs

项目八:讯飞语音

简介:讯飞语音JavaWeb语音合成解决方案。

项目地址:https://gitee.com/52itstyle/xufei_msc

小结

总结这一年来,收获还是蛮大的,通过开源本身技能得到提升,同时也接触了不少热爱技术的小伙伴。

没有对比就没有伤害,你一直想成为优秀的人,可是你却没有付出一丁点而的努力。你想想比你优秀的人都还在努力,你有什么资格不去努力!山无棱天地合,喂点鸡汤给大家。

转载于:https://www.cnblogs.com/cjm123/p/9723687.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
概要介绍:本门课程属于“Java分布式中间件大汇聚实战”系列课程,主要介绍了企业级项目中真实的应用场景的实现及主流的Java核心技术栈(Redis、RabbitMQ、Spring AOP、Redisson、ZooKeeper…)的实战等等。除此之外,还介绍了如何基于Redis设计并实战一款点赞系统(点赞、取消点赞、排行榜、用户中心、文章点赞用户列表…)可以说技术干货甚多,不仅可以巩固企业级应用系统的开发实战能力,相信在面试、跳槽涨薪方面也能带来相应的帮助!课程内容:传说中的金三银四、面试跳槽涨薪季已经来临,Debug特地为大家准备了一系列跟面试、跳槽、巩固核心技术栈相关的课程,本门课程属于第一季,其中的内容包括企业级项目中真实的应用场景实战、面试相关的技术点分享、主流的Java技术栈(Undertow、Redis、RabbitMQ、Spring AOP、Redisson、ZooKeeper…)实战等等。除此之外,我们还基于Redis设计并实战了一款点赞系统,可以说技术干货甚多。在课程的最后,Debug给大家整理了一份最新的面向BAT大厂招聘 ~ 2020年程序猿最新的Java面试题(附带目录和答案),希望对各位小伙伴的成长有所帮助!值得一提的是,本季课程实战的应用场景包括“日志记录”、“邮件发送”、“通告消息通知”、“短信验证码失效验证”、“会员到期自动提醒/到期前N天自动提醒”以及“点赞系统”的设计与实战,其大纲如下所示:其中,涉及到的技术栈包括Spring Boot2.0、Mybatis、Undertow、Redis、RabbitMQ、Redisson、Spring AOP、 Java8…下面罗列出本门课程重点介绍的价格应用案例以及业务场景的实现流程图!(1)基于Spring的消息驱动模型实现日志的异步记录:(2)基于消息中间件RabbitMQ的消息队列实现日志的异步记录:(3)基于缓存中间件Redis的订阅发布机制实现商户公告消息通知:(4)基于Redis的Key失效与定时任务实现实现短信验证码的过期失效验证:其他核心、典型的应用案例和业务场景的实战可以详细参考“课程目录”!除此之外,我们还基于缓存中间件Redis设计并实战实现了点赞系统中的点赞功能模块,下面罗列出其中涉及到的相关功能模块的实战流程图:其课程收益如下所示:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值