验证码Captcha的生成

前言

定义:

全自动区分计算机和人类的公开图灵测试

英语: Completely Automated Public Turing test to tell Computers and Humans Apart

俗称 验证码, 缩写为 Captcha.

首先,需要明白:

验证码是种反人类的存在。但它短时间内不可能退出历史舞台。我们需要尽量优化它,尽量提升用户的体验。

为什么要有验证码呢?

是为了证明网络的那端是一个人而不是一台机器(电脑)。

为什么要区分是人还是机器呢?

原因很多,归根结底,在于做坏事上,机器的效率比人高、成本比人低!

示例,臭名昭著的百度,极其恶心的验证码:

下面是验证码的几种常用场景:

1、账号安全。比如登录窗口,如果不设置验证码,可以使用脚本进行暴力破解。

2、防作弊。比如,12306 的验证码是为了防止机器恶意刷票。

3、反垃圾消息。比如,某些论坛上的验证码,防止机器群发的垃圾广告广告。

下面是几种常见可视化验证码的形式:

1、歪曲的字

2、倒立,点击

3、问答题

4、滑动拼图验证码

5、其他各种五花八门

他们有一个共同点,机器不容易辨认,可人类很容易就能识别。

现在,验证码技术也在不断发展。尤其是基于大数据的智能判断方兴未艾,按下不表。

验证码的原理


一个完整的验证逻辑分两步:

1、第一次请求 (获取阶段)

        a:服务器生成一个可以比较的对象,比如字符串或数字,并将其保存起来。一般保存到 Session 中。

        b:服务器根据上述生成的对象,构造出机器难以辨识的一段数据,比如声音、图片或短信,并发送给用户。

        c:数据在客户端展示,用户可以去识别

2、第二次请求, 携带用户输入的验证信息 (校验阶段)

      a:  用户将自己的数据,连带辨识出来的验证码数据,一并请求到服务器

      b:服务器将之前保存的原始数据,跟用户提交的作比较。如果相同,那么通过,否则不通过。

图片验证码


这是一种 最基本的验证方式, 其他所有的验证思路都是跟它一致的。

Java 中,绘制图片,需要用到 awt 包的 BufferedImage 类。

在获取阶段,客户端代码描述为:

<img src="captcha" title="验证码" />

<input name="captcha" />

服务端的代码描述为:

@WebServlet("/captcha")

classCaptchaServlet{

        public获得验证码的方法 () {

                //1. 获取随机字符串,作为原始验证字符串

                StringrandomString=getRandomString(4);

                //2. 根据字符串,生成机器难以辨认的图片

                BufferedImageimage=绘制图片(randomString);

                //3. 原始字符串 -> 保存起来

                session.setAttribute("captcha", randomString);

                //4. 绘制的图片 -> 发送给用户

                ImageIO.write(image,"PNG", response.getOutputStream()); 

         }

        /*根据字符串绘制图片*/

        BufferedImage 绘制图片(String randomString) {

                //1. 创建 Image 对象

                BufferedImageimage=newBufferedImage(w, h,BufferedImage.TYPE_INT_RGB);

                //2. 获取画笔

                Graphicsg=image.getGraphics();

                //3. 设置背景色

                g.setColor(getRandomColor()); 

                g.fillRect(0,0, w, h);

                //4. 绘制字符串

                g.setColor(getRandomColor());

                g.setFont(newFont(xxx, xxx, xxx)); 

                 g.drawString();

                //其他一些处理,变形扭曲等

                //5. 画干扰线和干扰点等g

                setColor(getRandomColor());

                g.drawLine();

                 g.drawOval();

                //6. 结束

                g.dispose();

                returnimage; 

         }

}

短信验证码

除了上述直接发送给用户浏览器的可视化验证码之外,在注册等场合,我们经常用到短信或邮箱验证。

这主要是为了防止账号被随意注册,从而进行恶意行为(僵尸粉,刷单等),也是奸商获取我们私人信息的重要途径(其实是为了提供更优服务哦~)。

有时候也是为了代替密码,绑定手机用来确保登录的安全性。

不管是图片验证码,还是短信、邮箱验证,道理都是一样的,区别在于发送给用户去辨认的数据不同、数据展示方式不同或数据接收媒介不同

短信验证 也是分为 验证码获取 和 校验 两个阶段! 获取验证码 这一步通常通过 Ajax 实现,并在服务端调用短信接口发送数据,数据不再通过浏览器展现,而是通过手机等其他媒介传递。

短信验证的简单代码描述为:

//1. 从 request 中得到用户的手机号码

Stringphone=request.getParameter("phone");

//2. 得到随机的字符串或数字

StringrandomNumber=getRandomNumber(4);

//3. 将得到的原始字符串保存起来

session.setAttribute("captcha", randomNumber);

//4. 调用短信接口服务,将原始字符串发送给用户

SMSInteface.sendMessage(phone, randomNumber);

至于短信接口服务,有很多。比如阿里大鱼, 它的使用很简单:

//1. 注册账号,获取 appkey 和 secret

//2. 申请短信签名,申请短信模板

//3. 为项目添加 jar 包: "com.aliyun:aliyun-java-sdk-dysmsapi:+"

//4. 编写程序,发送短信

publicvoidsendMessage(Stringphone,StringrandomNumber) {

              //1. 构造 request 对象

             AlibabaAliqinFcSmsNumSendRequestreq=newAlibabaAliqinFcSmsNumSendRequest();

            req.setRecNum(phone);            //发给谁

            req.setSmsType("normal");            //短息类型

            req.setSmsFreeSignName("123456");        //你的签名

           req.setSmsTemplateCode("SMS_585014");            //模板,需要自己在后台设置

           req.setSmsParamString("{,\"body\":\""+randomNumber+"\"}");        //发送内容,以参数形式传递给模板

}

邮箱验证码

邮箱验证,需要用到 J2EE 的 Java Mail 标准。

国外的网站,基本都是使用邮箱注册。它很基础很重要。

但道理相通,在此略过不提。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容