我们看到很多网站上都有验证码的功能,因为他们需要防止机器人注册等等,导致数据膨胀,或者是暴力破解,但是验证码做的难以破解是比较困难的,因为现在机器识别
功能是灰常强大的;要做一个比较难以被机器识别的验证码应该要扭曲旋转,连体,多色彩,干扰线,不要说什么来个微积分什么的,那是给普通人用的玩意吗?我们要追求
大众化,所以还是按照传统的标准来搞
我们看到网上都流传很多验证码框架,例如jcaptcha,kcaptcha等等.下面我展示下如何使用jcaptcha实现一个自定义的验证码,首先用过jcaptcha的人都知道他的验证码内容
是不支持放到cookie里面,而是放到本地的mapstore的fastmap里面,所以很明显是不支持集群的,所以下面也看看我是如何扩展
先扩展一个验证码的样式类
package com.silvery.plugin.validcode.jcaptcha;
import java.awt.Font;
import java.awt.image.ImageFilter;
import com.jhlabs.image.WaterFilter;
import com.octo.captcha.component.image.backgroundgenerator.AbstractBackgroundGenerator;
import com.octo.captcha.component.image.backgroundgenerator.FunkyBackgroundGenerator;
import com.octo.captcha.component.image.color.RandomRangeColorGenerator;
import com.octo.captcha.component.image.deformation.ImageDeformation;
import com.octo.captcha.component.image.deformation.ImageDeformationByFilters;
import com.octo.captcha.component.image.fontgenerator.FontGenerator;
import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;
import com.octo.captcha.component.image.textpaster.DecoratedRandomTextPaster;
import com.octo.captcha.component.image.textpaster.TextPaster;
import com.octo.captcha.component.image.textpaster.textdecorator.LineTextDecorator;
import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator;
import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;
import com.octo.captcha.component.image.wordtoimage.WordToImage;
import com.octo.captcha.component.word.wordgenerator.RandomWordGenerator;
import com.octo.captcha.component.word.wordgenerator.WordGenerator;
import com.octo.captcha.engine.image.ListImageCaptchaEngine;
import com.octo.captcha.image.gimpy.GimpyFactory;
/**
* 自定义验证码内容样式(通过源码改编)
*
* @author shadow
* @email 124010356@qq.com
* @create 2012.04.28
*/
public class SimpleCaptchaEngine extends ListImageCaptchaEngine {
/**
* this method should be implemented as folow :
* <ul>
* <li>First construct all the factories you want to initialize the gimpy
* with</li>
* <li>then call the this.addFactoriy method for each factory</li>
* </ul>
*/
protected void buildInitialFactories() {
// build filters 波浪实现类
WaterFilter water = new WaterFilter();
water.setAmplitude(3d);
water.setAntialias(true);
water.setPhase(30d);
water.setWavelength(80d);
ImageDeformation backDef = new ImageDeformationByFilters(new ImageFilter[] {});
ImageDeformation textDef = new ImageDeformationByFilters(new ImageFilter[] {});
ImageDeformation postDef = new ImageDeformationByFilters(new ImageFilter[] { water });
// word generator
WordGenerator dictionnaryWords = new RandomWordGenerator("abcdefhjkmnprstuvwxyz23456789");
// wordtoimage components
int[] R = new int[] { 0, 120 };
int[] G = new int[] { 0, 120 };
int[] B = new int[] { 0, 120 };
RandomRangeColorGenerator colors = new RandomRangeColorGenerator(R, G, B);
// Arial,Tahoma,Verdana,Helvetica,宋体,黑体,幼圆, 字体大小
Font[] fonts = new Font[] { new Font("Arial", 0, 10), new Font("Tahoma", 0, 10), new Font("Verdana", 0, 10),
new Font("Helvetica", 0, 10), new Font("宋体", 0, 10), new Font("黑体", 0, 10), new Font("幼圆", 0, 10) };
// 设置字符以及干扰线颜色
RandomRangeColorGenerator lineColors = new RandomRangeColorGenerator(R, G, B);
// 添加干扰线(可选取圆点干扰实现类BaffleTextDecorator LineTextDecorator)
TextPaster randomPaster = new DecoratedRandomTextPaster(4, 4, colors, true,
new TextDecorator[] { new LineTextDecorator(1, lineColors) });
RandomRangeColorGenerator backColorGenerator = new RandomRangeColorGenerator(new int[] { 75, 255 }, new int[] {
75, 255 }, new int[] { 75, 255 });
// 背景描绘
AbstractBackgroundGenerator back = new FunkyBackgroundGenerator(140, 50, backColorGenerator);
FontGenerator shearedFont = new RandomFontGenerator(35, 0, fonts);
// word2image 1
WordToImage word2image = new DeformedComposedWordToImage(shearedFont, back, randomPaster, backDef, textDef,
postDef);
// 输入图片
this.addFactory(new GimpyFactory(dictionnaryWords, word2image));
}
}
再写一个存放验证码类的实现类,简单的来说就是自己实现一个CaptchaStore接口的类,我们的验证码内容都是从这里读写
package com.silvery.plugin.validcode.jcaptcha;
import java.util.Collection;
import java.util.Locale;
import net.rubyeye.xmemcached.MemcachedClient;
import org.apache.commons.collections.CollectionUtils;
import com.octo.captcha.Captcha;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.captchastore.CaptchaAndLocale;
import com.octo.captcha.service.captchastore.CaptchaStore;
import com.silvery.core.spring.context.SpringHolder;
// Referenced classes of package com.octo.captcha.service.captchastore:
// CaptchaAndLocale, CaptchaStore
public class MemcacheCaptchaStore implements CaptchaStore {
private Object getCaptchaById(String id) {
try {
return getClient().get(id);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private MemcachedClient getClient() {
Object obj = SpringHolder.getBean(MemcachedClient.class);
if (obj == null) {
throw new RuntimeException("Not found memcache instance");
}
return (MemcachedClient) obj;
}
public boolean hasCaptcha(String id) {
try {
if (getCaptchaById(id) != null) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public void storeCaptcha(String id, Captcha captcha) throws CaptchaServiceException {
try {
getClient().set(id, 1800, new CaptchaAndLocale(captcha));
} catch (Exception e) {
e.printStackTrace();
}
}
public void storeCaptcha(String id, Captcha captcha, Locale locale) throws CaptchaServiceException {
try {
getClient().set(id, 1800, new CaptchaAndLocale(captcha, locale));
} catch (Exception e) {
throw new CaptchaServiceException(e);
}
}
public Captcha getCaptcha(String id) throws CaptchaServiceException {
try {
Object captchaAndLocale = getCaptchaById(id);
return captchaAndLocale == null ? null : ((CaptchaAndLocale) captchaAndLocale).getCaptcha();
} catch (Exception e) {
throw new CaptchaServiceException(e);
}
}
public Locale getLocale(String id) throws CaptchaServiceException {
try {
Object captchaAndLocale = getCaptchaById(id);
return captchaAndLocale == null ? null : ((CaptchaAndLocale) captchaAndLocale).getLocale();
} catch (Exception e) {
throw new CaptchaServiceException(e);
}
}
public boolean removeCaptcha(String id) {
try {
if (getCaptcha(id) != null) {
return getClient().delete(id);
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public int getSize() {
return 0;
}
public Collection<?> getKeys() {
return CollectionUtils.EMPTY_COLLECTION;
}
public void empty() {
}
public void initAndStart() {
}
public void cleanAndShutdown() {
}
}
基本的扩展类都搞好了,我们该在哪里传入给框架使用呢?请看下面的单例使用
package com.silvery.plugin.validcode.jcaptcha;
import com.octo.captcha.service.image.DefaultManageableImageCaptchaService;
import com.octo.captcha.service.image.ImageCaptchaService;
/**
*
* @author shadow
* @email 124010356@qq.com
* @create 2012.04.28
*/
public class SimpleCaptchaService {
private SimpleCaptchaService() {
// nothing
}
private static ImageCaptchaService instance = null;
/**
* SimpleListSoundCaptchaEngine //还可以用声音 SpellerSoundCaptchaEngine
* SpellerSoundCaptchaEngine DefaultGimpyEngineCaptcha
* BaffleListGimpyEngineCaptcha BasicListGimpyEngineCaptcha
* DeformedBaffleListGimpyEngineCaptcha DoubleRandomListGimpyEngineCaptcha
* SimpleListImageCaptchaEngineCaptcha SimpleFishEyeEngineCaptcha
*/
static {
instance = new DefaultManageableImageCaptchaService(new MemcacheCaptchaStore(), new SimpleCaptchaEngine(), 180,
100000, 75000);
}
public static ImageCaptchaService getInstance() {
return instance;
}
public static boolean validate(String s, Object input) {
return instance.validateResponseForID(s, input);
}
}
写个servlet让我们的页面可以访问生成出验证码图片
package com.silvery.plugin.validcode.jcaptcha;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.UUID;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.octo.captcha.service.CaptchaServiceException;
import com.silvery.security.variable.Const;
import com.silvery.utils.CookieUtils;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
/**
* jcaptcha图片生成
*
* @author shadow
* @email 124010356@qq.com
* @create 2012.04.28
*/
@SuppressWarnings("serial")
public class CaptchaServlet extends HttpServlet {
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
}
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws ServletException, IOException {
byte[] captchaChallengeAsJpeg = null;
// the output stream to render the captcha image as jpeg into
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try {
// get the session id that will identify the generated captcha.
// the same id must be used to validate the response, the session id
// is a good candidate!
String captchaId = UUID.randomUUID().toString();
// call the ImageCaptchaService getChallenge method
BufferedImage challenge = SimpleCaptchaService.getInstance().getImageChallengeForID(captchaId,
httpServletRequest.getLocale());
// a jpeg encoder
JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream);
jpegEncoder.encode(challenge);
httpServletResponse.addCookie(CookieUtils.createCookie(Const.USER_MODULE_JCAPTCHA, captchaId, 1800));
} catch (IllegalArgumentException e) {
httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
} catch (CaptchaServiceException e) {
httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
// flush it in the response
httpServletResponse.setHeader("Cache-Control", "no-store");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.setContentType("image/jpeg");
ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
}
}
最后我们配置下web.xml启动项目看看效果咯
<servlet>
<servlet-name>jcaptcha</servlet-name>
<servlet-class>com.silvery.plugin.validcode.jcaptcha.CaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jcaptcha</servlet-name>
<url-pattern>*.jcapt</url-pattern>
</servlet-mapping>
版权声明:本文为博主原创文章,未经博主允许不得转载。
分享到:
相关推荐
赠送jar包:shiro-config-core-1.4.0.jar; 赠送原API文档:shiro-config-core-1.4.0-javadoc.jar; 赠送源代码:shiro-config-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-config-core-1.4.0.pom; ...
赠送jar包:shiro-config-core-1.4.0.jar; 赠送原API文档:shiro-config-core-1.4.0-javadoc.jar; 赠送源代码:shiro-config-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-config-core-1.4.0.pom; ...
shiro_attack-4.7.0-SNAPSHOT-all.zip 序列化验证工具
给广大开发爱好者一个开发框架:shiro-root-1.4.1-source-release.zip
赠送jar包:shiro-event-1.4.0.jar; 赠送原API文档:shiro-event-1.4.0-javadoc.jar; 赠送源代码:shiro-event-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-event-1.4.0.pom; 包含翻译后的API文档:shiro-...
赠送jar包:shiro-cas-1.2.3.jar; 赠送原API文档:shiro-cas-1.2.3-javadoc.jar; 赠送源代码:shiro-cas-1.2.3-sources.jar; 赠送Maven依赖信息文件:shiro-cas-1.2.3.pom; 包含翻译后的API文档:shiro-cas-...
赠送jar包:shiro-crypto-cipher-1.4.0.jar; 赠送原API文档:shiro-crypto-cipher-1.4.0-javadoc.jar; 赠送源代码:shiro-crypto-cipher-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-crypto-cipher-1.4.0....
赠送jar包:shiro-crypto-core-1.4.0.jar; 赠送原API文档:shiro-crypto-core-1.4.0-javadoc.jar; 赠送源代码:shiro-crypto-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-crypto-core-1.4.0.pom; ...
shiro 安全框架--最好的中文配置文档,讲了shiro的配置步骤
赠送jar包:shiro-crypto-core-1.4.0.jar; 赠送原API文档:shiro-crypto-core-1.4.0-javadoc.jar; 赠送源代码:shiro-crypto-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-crypto-core-1.4.0.pom; ...
赠送jar包:shiro-core-1.4.0.jar; 赠送原API文档:shiro-core-1.4.0-javadoc.jar; 赠送源代码:shiro-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-core-1.4.0.pom; 包含翻译后的API文档:shiro-core...
shiro-root-1.2.4-source-release shiro-root-1.2.3-source-release shiro-all-1.2.4.jar shiro-all-1.2.4.jar shiro-all-1.2.4.jar shiro-all-1.2.4.jar
赠送jar包:shiro-config-ogdl-1.4.0.jar; 赠送原API文档:shiro-config-ogdl-1.4.0-javadoc.jar; 赠送源代码:shiro-config-ogdl-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-config-ogdl-1.4.0.pom; ...
shiro使用依赖的所有jar包,以及shiro-root-1.2.3-source-release的zip包
基于SpringMVC Mybatis Shiro Redis 的权限管理系统,该系统已经部署到线上,线上访问地址:http://shiro.itboy.net,登录账号:admin 密码:sojson,,详细教程参考sojson.com/shiro
shiro(shiro-all-1.8.0.jar)
赠送jar包:shiro-spring-1.3.2.jar; 赠送原API文档:shiro-spring-1.3.2-javadoc.jar; 赠送源代码:shiro-spring-1.3.2-sources.jar; 包含翻译后的API文档:shiro-spring-1.3.2-javadoc-API文档-中文(简体)版...
赠送jar包:shiro-crypto-cipher-1.4.0.jar; 赠送原API文档:shiro-crypto-cipher-1.4.0-javadoc.jar; 赠送源代码:shiro-crypto-cipher-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-crypto-cipher-1.4.0....
赠送jar包:shiro-crypto-hash-1.4.0.jar; 赠送原API文档:shiro-crypto-hash-1.4.0-javadoc.jar; 赠送源代码:shiro-crypto-hash-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-crypto-hash-1.4.0.pom; ...
赠送jar包:shiro-ehcache-1.4.0.jar; 赠送原API文档:shiro-ehcache-1.4.0-javadoc.jar; 赠送源代码:shiro-ehcache-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-ehcache-1.4.0.pom; 包含翻译后的API文档...