首页 技术 正文
技术 2022年11月6日
0 收藏 687 点赞 302 浏览 8270 个字

编写实现验证码的主体实现类:CaptchaCode

 import java.util.UUID; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert; import com.itzixi.common.utils.CookieUtils; /**
*
* @Title: CaptchaCode.java
* @Description: 验证码实现类
* @date 2017年10月14日 下午12:11:53
* @version V1.0
*/
public class CaptchaCode implements InitializingBean {
private final static Logger logger = LoggerFactory.getLogger(CaptchaCode.class);
private static final String DEFAULT_COOKIE_NAME = "itzixi-captcha";
private final static String DEFAULT_CHACHE_NAME = "itzixiCaptchaCache";
private final static int DEFAULT_MAX_AGE = -1; // cookie超时默认为session会话状态 private CacheManager cacheManager;
private String cacheName;
private String cookieName; private Cache<String, String> itzixiCaptchaCache; public CaptchaCode() {
this.cacheName = DEFAULT_CHACHE_NAME;
this.cookieName = DEFAULT_COOKIE_NAME;
} public CaptchaCode(CacheManager cacheManager) {
this();
this.cacheManager = cacheManager;
} public CacheManager getCacheManager() {
return cacheManager;
} public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
} public String getCacheName() {
return cacheName;
} public void setCacheName(String cacheName) {
this.cacheName = cacheName;
} public String getCookieName() {
return cookieName;
} public void setCookieName(String cookieName) {
this.cookieName = cookieName;
} @Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(cacheManager, "cacheManager must not be null!");
Assert.hasText(cacheName, "cacheName must not be empty!");
Assert.hasText(cookieName, "cookieName must not be empty!");
this.itzixiCaptchaCache = cacheManager.getCache(cacheName);
} /**
* 生成验证码
*/
public void generate(HttpServletRequest request, HttpServletResponse response) {
// 先检查cookie的uuid是否存在
String cookieValue = CookieUtils.getCookieValue(request, cookieName);
boolean hasCookie = true;
if (StringUtils.isBlank(cookieValue)) {
hasCookie = false;
cookieValue = UUID.randomUUID().toString();
}
String captchaCode = CaptchaUtils.generateCode().toUpperCase();// 转成大写重要
// 不存在cookie时设置cookie
if (!hasCookie) {
CookieUtils.setCookie(request, response, cookieName, cookieValue, DEFAULT_MAX_AGE);
}
// 生成验证码
CaptchaUtils.generate(response, captchaCode);
itzixiCaptchaCache.put(cookieValue, captchaCode);
} /**
* 仅能验证一次,验证后立即删除
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param userInputCaptcha 用户输入的验证码
* @return 验证通过返回 true, 否则返回 false
*/
public boolean validate(HttpServletRequest request, HttpServletResponse response, String userInputCaptcha) {
if (logger.isDebugEnabled()) {
logger.debug("validate captcha userInputCaptcha is " + userInputCaptcha);
}
String cookieValue = CookieUtils.getCookieValue(request, cookieName);
if (StringUtils.isBlank(cookieValue)) {
return false;
}
String captchaCode = itzixiCaptchaCache.get(cookieValue);
if (StringUtils.isBlank(captchaCode)) {
return false;
}
// 转成大写重要
userInputCaptcha = userInputCaptcha.toUpperCase();
boolean result = userInputCaptcha.equals(captchaCode);
if (result) {
itzixiCaptchaCache.remove(cookieValue);
CookieUtils.deleteCookie(request, response, cookieName);
}
return result;
}
}
CaptchaUtils.java
 import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.QuadCurve2D;
import java.awt.image.BufferedImage;
import java.util.Random; import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse; /**
*
* @Title: CaptchaUtils.java
* @Description: 验证码工具类
* @date 2017年10月14日 下午12:13:14
* @version V1.0
*/
class CaptchaUtils {
// 默认的验证码大小
private static final int WIDTH = 108, HEIGHT = 40, CODE_SIZE = 4;
// 验证码随机字符数组
protected static final char[] charArray = "3456789ABCDEFGHJKMNPQRSTUVWXY".toCharArray();
// 验证码字体
private static final Font[] RANDOM_FONT = new Font[] {
new Font("nyala", Font.BOLD, 38),
new Font("Arial", Font.BOLD, 32),
new Font("Bell MT", Font.BOLD, 32),
new Font("Credit valley", Font.BOLD, 34),
new Font("Impact", Font.BOLD, 32),
new Font(Font.MONOSPACED, Font.BOLD, 40)
}; /**
* 生成验证码
*/
static void generate(HttpServletResponse response, String vCode) {
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg"); ServletOutputStream sos = null;
try {
drawGraphic(image, vCode);
sos = response.getOutputStream();
ImageIO.write(image, "JPEG", sos);
sos.flush();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(sos);
}
} // 生成随机类
private static final Random RANDOM = new Random(); /**
* 生成验证码字符串
* @return 验证码字符串
*/
static String generateCode() {
int count = CODE_SIZE;
char[] buffer = new char[count];
for (int i = 0; i < count; i++) {
buffer[i] = charArray[RANDOM.nextInt(charArray.length)];
}
return new String(buffer);
} private static void drawGraphic(BufferedImage image, String code){
// 获取图形上下文
Graphics2D g = image.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
// 图形抗锯齿
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 字体抗锯齿
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // 设定背景色,淡色
g.setColor(getRandColor(210, 250));
g.fillRect(0, 0, WIDTH, HEIGHT); // 画小字符背景
Color color = null;
for(int i = 0; i < 20; i++){
color = getRandColor(120, 200);
g.setColor(color);
String rand = String.valueOf(charArray[RANDOM.nextInt(charArray.length)]);
g.drawString(rand, RANDOM.nextInt(WIDTH), RANDOM.nextInt(HEIGHT));
color = null;
}
// 取随机产生的认证码(4位数字)
char[] buffer = code.toCharArray();
for (int i = 0; i < buffer.length; i++){
char _code = buffer[i];
//旋转度数 最好小于45度
int degree = RANDOM.nextInt(28);
if (i % 2 == 0) {
degree = degree * (-1);
}
//定义坐标
int x = 22 * i, y = 21;
//旋转区域
g.rotate(Math.toRadians(degree), x, y);
//设定字体颜色
color = getRandColor(20, 130);
g.setColor(color);
//设定字体,每次随机
g.setFont(RANDOM_FONT[RANDOM.nextInt(RANDOM_FONT.length)]);
//将认证码显示到图象中
g.drawString("" + _code, x + 8, y + 10);
//旋转之后,必须旋转回来
g.rotate(-Math.toRadians(degree), x, y);
}
//图片中间曲线,使用上面缓存的color
g.setColor(color);
//width是线宽,float型
BasicStroke bs = new BasicStroke(3);
g.setStroke(bs);
//画出曲线
QuadCurve2D.Double curve = new QuadCurve2D.Double(0d, RANDOM.nextInt(HEIGHT - 8) + 4, WIDTH / 2, HEIGHT / 2, WIDTH, RANDOM.nextInt(HEIGHT - 8) + 4);
g.draw(curve);
// 销毁图像
g.dispose();
} /**
* 给定范围获得随机颜色
*/
private static Color getRandColor(int fc, int bc) {
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);
}
}
IOUtils.java
 import java.io.Closeable;
import java.io.IOException; /**
*
* @Title: IOUtils.java
* @Description: 流工具类,继承自Spring
* @date 2017年10月14日 下午12:13:04
* @version V1.0
*/
public class IOUtils extends org.springframework.util.StreamUtils { /**
* closeQuietly
* @param closeable 自动关闭
*/
public static void closeQuietly(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException ioe) {
// ignore
}
}
}

2、增加Bean的配置文件 在spring配置文件中增加:并采用缓存redis实现验证码的缓存存储

 <!--此Bean 只是增加登录时的验证码处理,不是shiro必须的配置-->
<bean class="com.itzixi.web.utils.CaptchaCode">
<!--<property name="cacheManager" ref="shiroEhcacheManager"/>-->
<property name="cacheManager" ref="shiroRedisCacheManager"></property>
<!-- 复用半小时缓存 -->
<property name="cacheName" value="cacheCaptcha"/>
</bean>

3、增加前端代码实现:

  <div class="form-group">
<label class="control-label visible-ie8 visible-ie9">密码</label>
<div id="input-error">
<input class="form-control form-control-solid placeholder-no-fix form-group" type="text"
autocomplete="off" placeholder="验证码" name="captcha" required/>
<a>
<img id="captcha" alt="验证码" src="<%=request.getContextPath() %>/captcha.action"
data-src="<%=request.getContextPath() %>/captcha.action?time="
style="width:94.5px;height:35px;"/>
</a>
</div>
</div>

在Controller增加/captcha.action 服务地址方法,调用验证码生成类进行验证码生成并加入到缓存中去

shiro 和spring集合  实现登录时输入验证码并校验(七)

4、在Controller层增加代码实现 接收,验证动作,如:CenterController.doPostlogin(….)

shiro 和spring集合  实现登录时输入验证码并校验(七)

  @RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public LeeJSONResult doPostlogin(String username, String password, String captcha,
@RequestParam(value = "isRememberMe", defaultValue = "0") Integer isRememberMe,
HttpServletRequest request, HttpServletResponse response) { if (StringUtils.isBlank(username)) {
return LeeJSONResult.errorMsg("用户名不能为空");
}
if (StringUtils.isBlank(password)) {
return LeeJSONResult.errorMsg("密码不能为空");
}
if (!captchaCode.validate(request, response, captcha)) {
return LeeJSONResult.errorMsg("验证码错误, 请重新输入...");
}
return LeeJSONResult.ok();
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,488
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,903
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,737
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,489
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,128
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,290