言
为了拦截大部分请求,秒杀案例前端引入了验证码。淘宝上很多人吐槽,等输入完秒杀活动结束了,对,结束了...... 当然了,验证码的真正作用是,有效拦截刷单操作,让羊毛党空手而归。
验证码
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
那么到底什么是验证码呢?验证码作为一种人机识别手段,其终极目的,就是区分正常人和机器的操作。我们常见的互联网注册、登录、发帖、领优惠券、投票等等应用场景,都有被机器刷造成各类损失的风险。
目前常见的验证码形式多为图片验证码,即数字、字母、文字、图片物体等形式的传统字符验证码。这类验证码看似简单易操作,但实际用户体验较差(参见12306网站),且随着OCR技术和打码平台的利用,图片比较容易被破解,被破解之后就形同虚设。
这里我们使用腾讯的智能人机安全验证码,告别传统验证码的单点防御,十道安全栅栏打造立体全面的安全验证,将黑产拒之门外。
场景
下面我们来瞅瞅验证码轻松解决了那些场景安全问题:
申请
申请地址:https://007.qq.com/product.html
在线体验:https://007.qq.com/online.html
只要一个QQ就可以免费申请,对于一般的企业OA系统或者个人博客网站,验证码免费套餐足够了已经,具备以下特点:
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:
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
@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(); // 显示验证码 },
后台监控
腾讯后台还提供了简单实用的数据监控,如下:
欢迎工作一到八年的Java工程师朋友们加入Java高级交流:854630135
本群提供免费的学习指导 架构资料 以及免费的解答
不懂得问题都可以在本群提出来 之后还会有直播平台和讲师直接交流噢
完小编前段时间发表的HTML学习之后,相信大家对网站建设与网页编写有了一定的初步了解,今天我们来开始介绍层叠样式表css,css是为HTML页面的排版美化而设计的,可以实现html无法设计的效果,一般是用来配合html来使用的,一般模式:选择器{属性:值}即selector{property:value}例如:body{corlor:red;font-size:12px;},他有三种引入方式:行内样式、内部样式表、外部样式表。
css三种嵌入方式:
一、行内样式
使用style属性引入CSS样式。
示例:
<h1 style="color:red;">style属性的应用</h1>
<p style="font-size:14px;color:green;">直接在HTML标签中设置的样式</p>
实际在写页面时不提倡使用,在测试的时候可以使用。
例如:
<!DOCTYPE> <html> <head> <meta charset="utf-8" /> <title>行内样式</title> </head> <body> <!--使用行内样式引入CSS--> <h1 style="color:red;">Leaping Above The Water</h1> <p style="color:red;font-size:30px;">我是p标签</p> </body> </html>
二、内部样式表
在style标签中书写CSS代码。style标签写在head标签中。
示例:
<head>
<style type="text/css">
h3{
color:red;
}
</style>
</head>
例如:<!DOCTYPE> <html> <head> <meta charset="utf-8" /> <title>内部样式表</title> <!--使用内部样式表引入CSS--> <style type="text/css"> div{ background: green; } </style> </head> <body> <div>我是DIV</div> </body> </html>
三、外部样式表
CSS代码保存在扩展名为.css的样式表中
HTML文件引用扩展名为.css的样式表,有两种方式:链接式、导入式。
语法:
1、链接式
<link type="text/css" rel="styleSheet" href="CSS文件路径" />
2、导入式
<style type="text/css">
@import url("css文件路径");
</style>
例如:<!DOCTYPE> <html> <head> <meta charset="utf-8" /> <title>外部样式表</title> <!--链接式:推荐使用--> <link rel="stylesheet" type="text/css" href="css/style.css" /> <!--导入式--> <style type="text/css"> @import url("css/style.css"); </style> </head> <body> <ol> <li>1111</li> <li>2222</li> </ol> </html>
行内样式>内部样式>外部样式(后两者是就近原则)。
css注释格式如下:
/* 注释如下*/
css中的颜色值表示如下:
可以是直接写英文单词,例如蓝色尽可以写blue;还可以写为十六进制字符,例如#rrggbb\#ffcc00,#rgb如:#fc0十六进制的颜色可以在颜色表中查询,这里我给大家提供一个,当然网上也有很多,大家也可以自己百度一下:
还有一种颜色的表示方式就是rbg模式,例如:
rgb(x,x,x) 其中x是一个0-255的整数值如:rgb(255,204,0)
rgb(x%,x%,x%) 其中x是一个0-100的整数值如rgb(100%,80%,0%)
Css的长度单位:
相对长度单位:px 像素(Pixel) em 相对于当前文本字体尺寸的倍数 % 百分比
绝对长度单位:in英寸(Inch) pt 点(Point) cm 厘米(Centimeter)mm 毫米(Millimeter)。
换算比例:1in = 2.54cm = 25.4 mm = 72pt
Css的七大类选择器:
标签选择器 例如:p{};
类选择器 例如.div{};(一个点加命名的类名)
Id选择器 例如 #div{};(斜体井号加ID名,ID是不可重复的,类可以相同)
通配符选择器:*{};
伪类选择器:
a:link{}没有访问时的链接;
a:visited{}已经访问过时的链接;
a:hove{}鼠标滑过时的链接;
a:active{}已经选中的链接;
:first-child{}为第一个字符设置样式;
:last-child{}为最后一个字符设置样式;
:nth-child(){}可以为指定字符设置样式
派生选择器(后代选择器、子元素选择器和相邻兄弟选择器):
后代选择器: 以空格分隔
div ul li {color:#0099cc;}
子元素选择器: 以>分隔
div >ul li
相邻兄弟选择器: 以+分隔
div + div ul li
最后一个就是组合选择器,以逗号隔开
h1, h2, h3, h4, h5, h6 { color: green }
好了,css基础就给大家介绍到这里,有什么不懂得地方可以给小编留言,如果您有什么好的建议也可以关注小编,我们共同学习,共同讨论,共同进步,接下来我们会介绍下css的属性,敬请期待吧
果想开发一个网站,除了要精通后端开发语言(如:php)外,还要精通HTML代码。那么,什么是HTML呢?HTML是一种超文本标记语言,它包含有众多的标签,我们可以通过这些标签,把不同的internet资源(如:文字、图片、视频、音频、表单等等)整合在一个统一的文档中,这就形成了我们可以看得见的网页。那么,HTML都有哪些常用的标签呢?
html5文档类型声明:<!doctype html>
html4文档类型声明:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
这个标签是html最外层的标签,所有其它的HTML标签都要放在这个标签的内部。
<html>
<head></head>
<body></body>
</html>
在HTML标签中,有的标签是成双成对的,如:<html></html>(如下图);而有的标签是单个的,如:<hr>横线标签。
head头部有以下几种常用标签:
meta:主要提供有关页面的元信息。
link:用来定义文档与外部资源的关系,最常用的是调用CSS样式文件。
title:页面标题的标签。
script:用来调用JS文件或JS代码。当然,script标签也可以在body主体中使用。
1、块级标签。
块级标签的特性是:独自占有一行;标签的高与宽、边距可以修改;没有设置宽与高时,默认继承父标签。例如:
<div>div1</div>
<div>div2</div>
<style>
.aa1{ border:1px solid #000; width:150px; height:100px; margin:30px; }
.aa2{ border:1px solid #000; width:150px; height:100px; margin:30px; }
</style>
前端页面显示的效果如下图:
常用的块级标签有:div、h1、h2、h3、h4、h5、h6、hr、menu、ul、ol、li、dl、dt、dd、table、p、form 。
2、内联标签。
内联标签与块级标签不同,它不能独自占有一行,会与其它内联标签在同一样展示;内联标签的高与宽、上下边距是不能修改的,它里面的文字或图片有多高,它就是多高。例如如下代码:
<style>
.aa1{ border:1px solid #000; width:150px; height:100px; margin:30px; }
.aa2{ border:1px solid #000; width:150px; height:100px; margin:30px; }
</style>
<span>span1</span>
<span>span2</span>
CSS样式代码跟块级标签的例子是一样的,而显示的效果就不一样了,宽与高、上下边距没有效果。如下图:
常用的内联标签有:span、a、b、strong、i、em 。
3、内联块级标签。
内联块级标签,既有一些内联标签的特性,也有一些块级标签的特点:它不能独自占有一行,但是可以修改它的宽度和高度。例如下面这段代码:
<style>
.aa1{ border:1px solid #000; width:150px; height:100px; margin:30px; }
.aa2{ border:1px solid #000; width:150px; height:100px; margin:30px; }
</style>
<img src="w5.jpg" alt="">
<img src="w5.jpg" alt="">
CSS样式代码跟块级标签的那个例子仍然是一样的,图片的宽和高、上下边距修改成功,而2个图片不能独自占有一行,而是在同一行。如下图:
常用的内联块级标签有:img、input、textarea。
4、区域标签。
所谓区域标签,就是主要用来划分布局页面区域的。如:头部、主体内容、侧边栏、底部。这样划分的好处是:让页面布局更加清晰明了。
常用的区域标签有:header(头部)、footer(底部)、nav(导航)、aside(侧边栏)、section(主体)、article(独立内容)。
5、表单标签。
这个表单标签我们也是会经常用到的,如:登录网站的时候、提交数据的时候。如下图的评论表单:
表单常用的标签有:form、input、select、option、textarea 。
以上就是我们开发网页时,会常用到的HTML标签。当然,HTML标签远不止这些,尤其是html5出来后,新增了许多的新标签。但是,有些标签在我们开发中很少用到,所以,这里就没有做相应的介绍。
*请认真填写需求信息,我们会在24小时内与您取得联系。