Ext随机验证码实现
来源:互联网 发布:编程时说a having been 编辑:程序博客网 时间:2024/05/22 01:55
上几篇文章,主要学习了 Extjs4 Grid 的使用方法,从本篇开始,我们开始其他组件的
学习,使用。在登录、注册甚至是发表文章或帖子的时候,都会用到验证码这个东西,那
么在 EXTJS 中,可以使用验证码功能么?答案是肯定的,在 EXTJS4 之前,也有很多验证
码的实现,在 Extjs4 中,验证码到底如何实现呢?
暂时,我们将验证码组件,命名为 CheckCode。此组件继承自 Ext.form.field.Text,在
实现之前,我们需要写两个样式,分别用来控制验证码的输入框和验证码图片的大小。
CSS 样式为:
- #CheckCode{ float:left;}
- .x-form-code{width:73px;height:20px;vertical-align:middle;cursor:pointer; float:left; margin-left:7px;}
#CheckCode{ float:left;} .x-form-code{width:73px;height:20px;vertical-align:middle;cursor:pointer; float:left; margin-left:7px;}
记住这两个样式的定义,后面,我们会用到它。
验证码的 JS 代码(CheckCode.js):
- Ext.define('SMS.view.CheckCode', {
- extend: 'Ext.form.field.Text',
- alias: 'widget.checkcode',
- inputType: 'codefield',
- codeUrl: Ext.BLANK_IMAGE_URL,
- isLoader: true,
- onRender: function(ct, position) {
- this.callParent(arguments);
- this.codeEl = ct.createChild({
- tag: 'img',
- src: Ext.BLANK_IMAGE_URL
- });
- this.codeEl.addCls('x-form-code');
- this.codeEl.on('click', this.loadCodeImg, this);
- if(this.isLoader) {
- this.loadCodeImg();
- }
- },
- aliasErrorIcon: function() {
- this.errorIcon.alignTo(this.codeEl, 'tl-tr', [2, 0]);
- },
- loadCodeImg: function() {
- //如果浏览器发现url不变,就认为图片没有改变,就会使用缓存中的图片,而不是重新向服务器请求,所以需要加一个参数,改变url
- this.codeEl.set({
- src: this.codeUrl + '?id=' + Math.random()
- });
- }
- });
Ext.define('SMS.view.CheckCode', { extend: 'Ext.form.field.Text', alias: 'widget.checkcode', inputType: 'codefield', codeUrl: Ext.BLANK_IMAGE_URL, isLoader: true, onRender: function(ct, position) { this.callParent(arguments); this.codeEl = ct.createChild({ tag: 'img', src: Ext.BLANK_IMAGE_URL }); this.codeEl.addCls('x-form-code'); this.codeEl.on('click', this.loadCodeImg, this); if(this.isLoader) { this.loadCodeImg(); } }, aliasErrorIcon: function() { this.errorIcon.alignTo(this.codeEl, 'tl-tr', [2, 0]); }, loadCodeImg: function() { //如果浏览器发现url不变,就认为图片没有改变,就会使用缓存中的图片,而不是重新向服务器请求,所以需要加一个参数,改变url this.codeEl.set({ src: this.codeUrl + '?id=' + Math.random() }); }});
以上代码中,定义了一个―类‖,名字是:SMS.view.CheckCode,其实这个名字,相当
于 extjs 3.x 之中的命名空间,以前也提到过。它继承自 Ext.form.field.Text,在它的
onRender 中,我们写了一些代码。其中 this.callParent(arguments); 代替了
xxxx.superclass.onRender.call(this, ct, position);在 Ext.form.field.Text 的基础上,使用
createChild 方法,创建了一个图片,并为其添加了一个名为 x-form-code,而后,给其创建
了一个 click 事件,这个事件实现的功能是,当我们点击验证码图片时,换另外一张图片,
也就是常说的:―看不清?换一张功能。‖,最后,如果 isLoader 为 True 时,调用
loadCodeImg 方法。至此,验证码功能全部完成了。下面,我们看看如何使用。
新建 Login.js 文件,定义―类‖SMS.view.Login,其全部代码为(Login.js):
- Ext.define('SMS.view.Login', {
- extend: 'Ext.window.Window',
- alias: 'widget.loginForm',
- requires: [
- 'Ext.form.*',
- 'SMS.view.CheckCode'
- ],
- initComponent: function() {
- var checkcode = Ext.create('SMS.view.CheckCode', {
- cls: 'key',
- fieldLabel: '验证码',
- name: 'checkcode',
- id: 'checkcode',
- allowBlank: false,
- isLoader: true,
- blankText: '验证码不能为空',
- codeUrl: 'rand.action',
- width: 160
- });
- var form = Ext.widget('form', {
- border: false,
- bodyPadding: 10,
- fieldDefaults: {
- labelAlign: 'left',
- labelWidth: 55,
- labelStyle: 'font-weight: bold'
- },
- defaults: {
- margins: '0 0 10 0'
- },
- items: [{
- xtype: 'textfield',
- id: 'username',
- name: 'username',
- fieldLabel: '用户名',
- blankText: '用户名不能为空',
- allowBlank: false,
- width: 240
- }, {
- xtype: 'textfield',
- id: 'password',
- name: 'password',
- fieldLabel: '密 码',
- allowBlank: false,
- blankText: '密码不能为空',
- width: 240,
- inputType: 'password'
- }, checkcode],
- buttons: [{
- text: '登录',
- handler: function() {
- //获取当前的表单form
- var form = this.up('form').getForm();
- //判断否通过了表单验证,如果不能空的为空则不能提交
- if (form.isValid()) {
- //alert("可以提交");
- form.submit({
- clientValidation : true,
- waitMsg : '请稍候',
- waitTitle : '正在验证登录',
- url : 'login.action',
- success : function(form, action) {
- //登录成功后的操作,这里只是提示一下
- Ext.MessageBox.show({
- width : 150,
- title : "登录成功",
- buttons : Ext.MessageBox.OK,
- msg : action.result.msg
- })
- },
- failure : function(form, action) {
- Ext.MessageBox.show({
- width : 150,
- title : "登录失败",
- buttons : Ext.MessageBox.OK,
- msg : action.result.msg
- })
- }
- })
- }
- }
- }, {
- text: '取消',
- handler: function() {
- //点击取消,关闭登录窗口
- // var form = this.up('form');
- // form.close();
- }
- }]
- });
- Ext.apply(this, {
- height: 160,
- width: 280,
- title: '用户登录',
- closeAction: 'hide',
- closable: false,
- iconCls: 'login',
- layout: 'fit',
- modal: true,
- plain: true,
- resizable: false,
- items: form
- });
- this.callParent(arguments);
- }
- });
Ext.define('SMS.view.Login', { extend: 'Ext.window.Window', alias: 'widget.loginForm', requires: [ 'Ext.form.*', 'SMS.view.CheckCode' ], initComponent: function() { var checkcode = Ext.create('SMS.view.CheckCode', { cls: 'key', fieldLabel: '验证码', name: 'checkcode', id: 'checkcode', allowBlank: false, isLoader: true, blankText: '验证码不能为空', codeUrl: 'rand.action', width: 160 }); var form = Ext.widget('form', { border: false, bodyPadding: 10, fieldDefaults: { labelAlign: 'left', labelWidth: 55, labelStyle: 'font-weight: bold' }, defaults: { margins: '0 0 10 0' }, items: [{ xtype: 'textfield', id: 'username', name: 'username', fieldLabel: '用户名', blankText: '用户名不能为空', allowBlank: false, width: 240 }, { xtype: 'textfield', id: 'password', name: 'password', fieldLabel: '密 码', allowBlank: false, blankText: '密码不能为空', width: 240, inputType: 'password' }, checkcode], buttons: [{ text: '登录', handler: function() { //获取当前的表单form var form = this.up('form').getForm(); //判断否通过了表单验证,如果不能空的为空则不能提交 if (form.isValid()) { //alert("可以提交"); form.submit({ clientValidation : true, waitMsg : '请稍候', waitTitle : '正在验证登录', url : 'login.action', success : function(form, action) { //登录成功后的操作,这里只是提示一下 Ext.MessageBox.show({ width : 150, title : "登录成功", buttons : Ext.MessageBox.OK, msg : action.result.msg }) }, failure : function(form, action) { Ext.MessageBox.show({ width : 150, title : "登录失败", buttons : Ext.MessageBox.OK, msg : action.result.msg }) } }) } } }, { text: '取消', handler: function() { //点击取消,关闭登录窗口 // var form = this.up('form'); // form.close(); } }] }); Ext.apply(this, { height: 160, width: 280, title: '用户登录', closeAction: 'hide', closable: false, iconCls: 'login', layout: 'fit', modal: true, plain: true, resizable: false, items: form }); this.callParent(arguments); }});
程序的入口(app.js):
- Ext.application({
- name: 'SMS',
- appFolder: 'app',
- launch: function() {
- requires: ['SMS.view.Login']
- var win;
- win = Ext.create('SMS.view.Login').show();
- }
- });
Ext.application({ name: 'SMS', appFolder: 'app', launch: function() { requires: ['SMS.view.Login'] var win; win = Ext.create('SMS.view.Login').show(); } });
login.jsp:
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>用户登录</title>
- <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" />
- <script type="text/javascript" src="extjs/ext-all.js"></script>
- <script type="text/javascript" src="extjs/ext-lang-zh_CN.js"></script>
- <script type="text/javascript" src="app.js"></script>
- <style type="text/css">
- #checkcode {
- float: left;
- }
- .x-form-code {
- width: 73px;
- height: 20px;
- vertical-align: middle;
- cursor: pointer;
- float: left;
- margin-left: 7px;
- }
- </style>
- </head>
- <body>
- </body>
- </html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html> <head> <base href="<%=basePath%>"> <title>用户登录</title><link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" /><script type="text/javascript" src="extjs/ext-all.js"></script><script type="text/javascript" src="extjs/ext-lang-zh_CN.js"></script><script type="text/javascript" src="app.js"></script><style type="text/css">#checkcode {float: left;}.x-form-code {width: 73px;height: 20px;vertical-align: middle;cursor: pointer;float: left;margin-left: 7px;}</style> </head> <body> </body></html>
生成随机验证码的类( RandomNumUtil.java):
- package org.changkong.sms.utils;
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.Graphics;
- import java.awt.image.BufferedImage;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.util.Random;
- import javax.imageio.ImageIO;
- import javax.imageio.stream.ImageOutputStream;
- /**
- * 生成验证码的类文件
- *
- */
- public class RandomNumUtil {
- private ByteArrayInputStream image; //图像
- private String str; //验证码
- private RandomNumUtil() {
- init(); //初始化属性
- }
- /*
- * 取得RandomNumUtil实例
- */
- public static RandomNumUtil Instance() {
- return new RandomNumUtil();
- }
- /*
- * 取得验证码图片
- */
- public ByteArrayInputStream getImage() {
- return this.image;
- }
- /*
- * 取得图片的验证码
- */
- public String getString() {
- return this.str;
- }
- private void init() {
- //在内存中创建图象
- //图像的高度和宽度
- int width = 55, height = 20;
- BufferedImage image = new BufferedImage(width, height,
- BufferedImage.TYPE_INT_RGB);
- //获取图形上下文
- Graphics g = image.getGraphics();
- //生成随机类
- Random random = new Random();
- //设定背景色
- g.setColor(getRandColor(200, 250));
- g.fillRect(0, 0, width, height);
- //设定字体
- g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
- //随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
- g.setColor(getRandColor(160, 200));
- for (int i = 0; i < 155; i++) {
- int x = random.nextInt(width);
- int y = random.nextInt(height);
- int xl = random.nextInt(12);
- int yl = random.nextInt(12);
- g.drawLine(x, y, x + xl, y + yl);
- }
- //取随机产生的认证码(6位数字)
- String sRand = "";
- for (int i = 0; i < 4; i++) {
- String rand = String.valueOf(random.nextInt(10));
- sRand += rand;
- //将认证码显示到图象中
- g.setColor(new Color(20 + random.nextInt(110), 20 + random
- .nextInt(110), 20 + random.nextInt(110)));
- //调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
- g.drawString(rand, 13 * i + 6, 16);
- }
- //赋值验证码
- this.str = sRand;
- //图象生效
- g.dispose();
- ByteArrayInputStream input = null;
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- try {
- ImageOutputStream imageOut = ImageIO
- .createImageOutputStream(output);
- ImageIO.write(image, "JPEG", imageOut);
- imageOut.close();
- input = new ByteArrayInputStream(output.toByteArray());
- } catch (Exception e) {
- System.out.println("验证码图片产生出现错误:" + e.toString());
- }
- this.image = input;/* 赋值图像 */
- }
- /*
- * 给定范围获得随机颜色
- */
- private Color getRandColor(int fc, int bc) {
- Random random = new Random();
- if (fc > 255)
- fc = 255;
- if (bc > 255)
- bc = 255;
- int r = fc + random.nextInt(bc - fc);
- int g = fc + random.nextInt(bc - fc);
- int b = fc + random.nextInt(bc - fc);
- return new Color(r, g, b);
- }
- }
package org.changkong.sms.utils;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.util.Random;import javax.imageio.ImageIO;import javax.imageio.stream.ImageOutputStream;/** * 生成验证码的类文件 * */public class RandomNumUtil {private ByteArrayInputStream image; //图像private String str;//验证码private RandomNumUtil() {init();//初始化属性}/* * 取得RandomNumUtil实例 */public static RandomNumUtil Instance() {return new RandomNumUtil();}/* * 取得验证码图片 */public ByteArrayInputStream getImage() {return this.image;}/* * 取得图片的验证码 */public String getString() {return this.str;}private void init() {//在内存中创建图象//图像的高度和宽度int width = 55, height = 20;BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);//获取图形上下文Graphics g = image.getGraphics();//生成随机类Random random = new Random();//设定背景色g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height);//设定字体g.setFont(new Font("Times New Roman", Font.PLAIN, 18));//随机产生155条干扰线,使图象中的认证码不易被其它程序探测到g.setColor(getRandColor(160, 200));for (int i = 0; i < 155; i++) {int x = random.nextInt(width);int y = random.nextInt(height);int xl = random.nextInt(12);int yl = random.nextInt(12);g.drawLine(x, y, x + xl, y + yl);}//取随机产生的认证码(6位数字)String sRand = "";for (int i = 0; i < 4; i++) {String rand = String.valueOf(random.nextInt(10));sRand += rand;//将认证码显示到图象中g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成g.drawString(rand, 13 * i + 6, 16);}//赋值验证码this.str = sRand;//图象生效g.dispose();ByteArrayInputStream input = null;ByteArrayOutputStream output = new ByteArrayOutputStream();try {ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);ImageIO.write(image, "JPEG", imageOut);imageOut.close();input = new ByteArrayInputStream(output.toByteArray());} catch (Exception e) {System.out.println("验证码图片产生出现错误:" + e.toString());}this.image = input;/* 赋值图像 */}/* * 给定范围获得随机颜色 */private Color getRandColor(int fc, int bc) {Random random = new Random();if (fc > 255)fc = 255;if (bc > 255)bc = 255;int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}}
验证码的Action(SecurityCodeAction.java):
- package org.changkong.sms.action;
- import java.io.ByteArrayInputStream;
- import org.changkong.sms.utils.RandomNumUtil;
- import org.springframework.context.annotation.Scope;
- import org.springframework.stereotype.Controller;
- import com.opensymphony.xwork2.ActionContext;
- import com.opensymphony.xwork2.ActionSupport;
- /**
- * 验证码的Action
- * 使用SSH集成开发,Action由Spring管理
- */
- @Controller("sercurityCodeAction")
- @Scope("prototype")
- public class SecurityCodeAction extends ActionSupport {
- private ByteArrayInputStream inputStream;
- public String execute() throws Exception {
- RandomNumUtil rdnu = RandomNumUtil.Instance();
- //取得带有随机字符串的图片
- this.setInputStream(rdnu.getImage());
- //取得随机字符串放入HttpSession
- ActionContext.getContext().getSession().put("random", rdnu.getString());
- return SUCCESS;
- }
- public void setInputStream(ByteArrayInputStream inputStream) {
- this.inputStream = inputStream;
- }
- public ByteArrayInputStream getInputStream() {
- return inputStream;
- }
- }
package org.changkong.sms.action;import java.io.ByteArrayInputStream;import org.changkong.sms.utils.RandomNumUtil;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Controller;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;/** * 验证码的Action * 使用SSH集成开发,Action由Spring管理 */@Controller("sercurityCodeAction")@Scope("prototype")public class SecurityCodeAction extends ActionSupport {private ByteArrayInputStream inputStream;public String execute() throws Exception {RandomNumUtil rdnu = RandomNumUtil.Instance();//取得带有随机字符串的图片this.setInputStream(rdnu.getImage());//取得随机字符串放入HttpSessionActionContext.getContext().getSession().put("random", rdnu.getString());return SUCCESS;}public void setInputStream(ByteArrayInputStream inputStream) {this.inputStream = inputStream;}public ByteArrayInputStream getInputStream() {return inputStream;}}
登录Action(LoginAction.java):
- package org.changkong.sms.action;
- import org.apache.struts2.ServletActionContext;
- import org.springframework.context.annotation.Scope;
- import org.springframework.stereotype.Controller;
- import com.opensymphony.xwork2.ActionContext;
- /**
- * 登录Action
- */
- @Controller("loginAction")
- @Scope("prototype")
- public class LoginAction {
- private String username;
- private String password;
- private String checkcode; // 表单中的rand
- //从session中取出RandomAction.java 中生成的验证码random
- String arandom = (String) (ActionContext.getContext().getSession().get("random"));
- public String execute() {
- if(!arandom.equals(checkcode)) {
- System.out.println("验证码不正确");
- } else if(!"admin".equals(username)) {
- System.out.println("用户不存在");
- } else if("admin".equals(password)) {
- System.out.println("密码错误");
- }
- return "success";
- }
- public String logout() {
- ServletActionContext.getRequest().getSession().invalidate();
- return "logout";
- }
- public String getCheckcode() {
- return checkcode;
- }
- public void setCheckcode(String checkcode) {
- this.checkcode = checkcode;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
package org.changkong.sms.action;import org.apache.struts2.ServletActionContext;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Controller;import com.opensymphony.xwork2.ActionContext;/** * 登录Action */@Controller("loginAction")@Scope("prototype")public class LoginAction {private String username;private String password;private String checkcode; // 表单中的rand//从session中取出RandomAction.java 中生成的验证码randomString arandom = (String) (ActionContext.getContext().getSession().get("random"));public String execute() {if(!arandom.equals(checkcode)) {System.out.println("验证码不正确");} else if(!"admin".equals(username)) {System.out.println("用户不存在");} else if("admin".equals(password)) {System.out.println("密码错误");}return "success";}public String logout() {ServletActionContext.getRequest().getSession().invalidate();return "logout";}public String getCheckcode() {return checkcode;}public void setCheckcode(String checkcode) {this.checkcode = checkcode;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}
Struts.xml:
- <!-- 用户登陆 -->
- <action name="login" class="loginAction">
- <!-- LoginAction无需经过LoginInterceptor -->
- <interceptor-ref name="defaultStack"></interceptor-ref>
- <result name="success" type="redirect">/main.jsp</result>
- <result name="fail">/login.jsp</result>
- <result name="logout">/login.jsp</result>
- </action>
- <!-- Random验证码 -->
- <action name="rand" class="sercurityCodeAction">
- <result type="stream">
- <param name="contentType">image/jpeg</param>
- <param name="inputName">inputStream</param>
- </result>
- </action>
- Ext随机验证码实现
- Servlet实现随机验证码
- 动手实现随机验证码
- 如何实现随机验证码
- 随机图片验证码实现
- js 实现随机验证码
- 随机验证码实现案例
- Java 实现随机验证码
- 画布实现随机验证码
- Ext中实现 简单验证码效果
- ext 实现 异步验证
- 用Java实现随机验证码功能
- Java实现随机验证码功能实例
- Java实现随机验证码功能实例
- Java实现随机验证码功能实例
- Java实现随机验证码功能实例
- Java实现随机验证码功能实例
- 用PHP实现随机验证码功能
- ubuntu13.04正式版启动root登陆系统
- CygWin 为Hadoop配置Java_Home
- Linux程序设计第四章
- SQL查询同一字段下相同的记录,并只显示有相同记录的
- CUDA: CUBLAS - hello cublas
- Ext随机验证码实现
- 微信公众帐号开发教程第15篇-自定义菜单的view类型(访问网页)(15)
- vba 数组(动态数组)
- GitHub on Ubuntu 小贴士
- Linux程序设计第五章
- awk的使用 第4部分 在awk中使用数组
- 通过wifi调试android程序
- 使用 idHTTP 获取 UTF-8 编码的中文网页 - 回复同学 "Delphi学习者" 的问题
- 远程研讨会邀请函(2013-10-25)