验证码及它的作用
验证码为全自动区分计算机和人类的图灵测试的缩写,是一种区分用户是计算机的公共全自动程序,这个问题可以由计算机生成并评判,但是必须只有人类才能解答.可以防止恶意破解密码、刷票、论坛灌水、有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录。
图文验证码的原理
在servlet中随机生成一个指定位置的验证码,一般为四位,然后把该验证码保存到session中.在通过Java的绘图类以图片的形式输出该验证码。为了增加验证码的安全级别,可以输出图片的同时输出干扰线,最后在用户提交数据的时候,在服务器端将用户提交的验证码和Session保存的验证码进行比较。
实现方式总结
1 验证码生成类RandomCode
RandomCode是一个生成验证码的工具类,支持英文和数字验证码,验证码包括英文大小写和数组,其中英文i、o和数字0、1因为容易产生混淆,不包括在生成验证码中。RandomCode支持输出jpg/bmp/png/gif图片格式的验证码。
/** * RandomCode验证码可以通过静态方法和实例方法生成。 * * 静态方法: * * //生成长度为4的随机验证码 * String code = RandomCode.randomString(4); * * //把验证码图片输入到response输出流中 * //图片格式jpg * OutputStream os = response.getOutputStream(); * RandomCode.write(code, 120, 30, os, "jpg"); * * 实例方法: * * //实例化验证码类 * RandomCode rc = new RandomCode(4); * * //把验证码图片输入到response输出流中 * //图片格式jpg * OutputStream os = response.getOutputStream(); * rc.write(120, 30, os, "jpg"); * * //获取验证码字符串 * String code = rc.getCode(); * */ public class RandomCode { /** * 随机验证码字符 */ private static String base = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"; /** * 随机验证码长度 */ private int length = 4; /** * 验证码字符串 */ private String code; /** * 4位随机验证码 */ public RandomCode(){ this.code = RandomCode.randomString(this.length); } public RandomCode(int length){ if(length > 0){ this.length = length; } this.code = RandomCode.randomString(this.length); } /** * 生成验证码图片 * @param width 图片宽度 * @param height 图片高度 * @return */ public BufferedImage toImage(int width, int height){ return RandomCode.toImage(this.code, width, height); } /** * 输出验证码图片,默认图片格式jpeg * @param width * @param height * @param os * @throws IOException */ public void write(int width, int height, OutputStream os) throws IOException{ RandomCode.write(code, width, height, os, "jpeg"); } /** * 输出验证码图片 * @param width * @param height * @param os * @param format 图片格式,支持jpg/jpeg/bmp/gif/png * @throws IOException */ public void write(int width, int height, OutputStream os, String format) throws IOException{ RandomCode.write(code, width, height, os, format); } public int getLength() { return length; } public String getCode() { return code; } /** * 静态方法 * 生成随机字符串 * @param length 字符串长度 * @return 随机字符串 */ public static String randomString(int length){ Random random = new Random(); StringBuffer sb = new StringBuffer(); for(int i = 0; i < length; i++){ sb.append(base.charAt(random.nextInt(base.length()))); } return sb.toString(); } /** * 静态方法 * 输出验证码图片 * @param code 验证码字符串 * @param width 图片宽度 * @param height 图片高度 * @param os 图片输出流 * @param format 图片格式,支持jpg/jpeg/bmp/gif/png * @throws IOException */ public static void write(String code, int width, int height, OutputStream os, String format) throws IOException{ BufferedImage image = toImage(code, width, height); ImageIO.write(image, format, os); } /** * 静态方法 * 输出验证码图片,默认图片格式jpeg * @param code 验证码字符串 * @param width 图片宽度 * @param height 图片高度 * @param os 图片输出流 * @throws IOException */ public static void write(String code, int width, int height, OutputStream os) throws IOException{ write(code, width, height, os, "jpeg"); } /** * 静态方法 * 字符串转成验证码图片 * @param code 验证码字符串 * @param width 验证码图片宽度,单位像素 * @param height 验证码图片高度,单位像素 * @return */ public static BufferedImage toImage(String code, int width, int height){ //字体大小 int fontSize = (int)Math.ceil(height * 0.9); if(fontSize < 20){ fontSize = 20; } //字体在Y坐标上的位置 int positionY = (int)Math.ceil(height * 0.8); int lenCode = code.length(); //计算字体宽度 int fontWidth = width / (lenCode + 2); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); Graphics g = image.getGraphics(); //图片背景随机颜色 g.setColor(randomColor(new Random(), 200, 250)); g.fillRect(0, 0, width, height); //设置字体 g.setFont(new Font("Times New Roman", Font.BOLD, fontSize)); //在图片上画纵横交错的线,达到混淆效果 drawLines(g, width, height); //在图片上画验证码 drawString(g, code, fontWidth, positionY); g.dispose(); return image; } /** * 静态方法 * 在图片上话位子 * @param g * @param code 验证码字符串 * @param fontWidth 字体宽度 * @param positionY 字体Y坐标 */ private static void drawString(Graphics g, String code, int fontWidth, int positionY){ int len = code.length(); Random random = new Random(); for(int i = 0; i < len; i++){ g.setColor(randomColor(random)); g.drawString(String.valueOf(code.charAt(i)), (i + 1) * fontWidth, positionY); } } private static Color randomColor(Random random){ int r = random.nextInt(255); int g = random.nextInt(255); int b = random.nextInt(255); return new Color(r, g, b); } private static Color randomColor(Random random, int fc, int bc){ if(fc > 255){ fc = 255; } if(bc > 255){ bc = 255; } int diff = bc-fc; int r = fc + random.nextInt(diff); int g = fc + random.nextInt(diff); int b = fc + random.nextInt(diff); return new Color(r,g,b); } /** * 静态方法 * 画纵横交错的线 * @param g * @param width 验证码图片宽度 * @param height 验证码图片高度 */ private static void drawLines(Graphics g, int width, int height){ Random random = new Random(); //线的数量 int count = ((int)(Math.ceil(random.nextDouble() * 100))) + 100; for(int i = 0; i < count; i++){ int fc = 160 + (int)Math.ceil(random.nextDouble() * 40); int bc = 200 + (int)Math.ceil(random.nextDouble() * 55); g.setColor(randomColor(random, fc, bc)); int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(width / 5); int yl = random.nextInt(height / 5); g.drawLine(x, y, x + xl, y + yl); } } }
2 Servlet返回验证码
请求路径http://<网站路径>/random/code/servlet
@WebServlet("/random/code/servlet") public class RandomCodeServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 验证码图片宽度,单位像素 int width = 120; // 验证码图片高度,单位像素 int height = 30; // 验证码图片格式 String format = "png"; // 验证码字符长度 int len = 4; // 设置图片格式 response.setContentType("image/" + format); // 禁止浏览器缓存图片 response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); String code = RandomCode.randomString(len); // 把图片输出到response输出流 RandomCode.write(code, width, height, response.getOutputStream(), format); } }
3 Strust2返回验证码
public class RandomCodeAction extends ActionSupport { private static final long serialVersionUID = -7515645222798283236L; /** * 获取验证码 */ public void generateCode() { HttpServletResponse response = ServletActionContext.getResponse(); // 验证码图片宽度,单位像素 int width = 120; // 验证码图片高度,单位像素 int height = 30; // 验证码图片格式 String format = "png"; // 验证码字符长度 int len = 4; // 设置图片格式 response.setContentType("image/" + format); // 禁止浏览器缓存图片 response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); String code = RandomCode.randomString(len); // 把图片输出到response输出流 try { RandomCode.write(code, width, height, response.getOutputStream(), format); } catch (IOException e) { e.printStackTrace(); } } }
Struts2的验证码配置
<package name="pkg-random-code" namespace="/" extends="struts-default"> <action name="randomCode_*" method="{1}" class="com.rhui.web.action.RandomCodeAction"></action> </package>
请求路径http://<网站路径>/randomCode_generateCode.do
4 SpringMVC返回验证码
请求路径http://<网站路径>/random/code/generate.do
package com.rhui.web.controller; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.rhui.util.RandomCode; @Controller @RequestMapping("/random/code") public class RandomCodeController { @RequestMapping("/generate.do") public void generateCode(HttpServletResponse response) { // 验证码图片宽度,单位像素 int width = 120; // 验证码图片高度,单位像素 int height = 30; // 验证码图片格式 String format = "png"; // 验证码字符长度 int len = 4; // 设置图片格式 response.setContentType("image/" + format); // 禁止浏览器缓存图片 response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); String code = RandomCode.randomString(len); // 把图片输出到response输出流 try { RandomCode.write(code, width, height, response.getOutputStream(), format); } catch (IOException e) { e.printStackTrace(); } } }
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 中国武警男声合唱团《辉煌之声1天路》[DTS-WAV分轨]
- 紫薇《旧曲新韵》[320K/MP3][175.29MB]
- 紫薇《旧曲新韵》[FLAC/分轨][550.18MB]
- 周深《反深代词》[先听版][320K/MP3][72.71MB]
- 李佳薇.2024-会发光的【黑籁音乐】【FLAC分轨】
- 后弦.2012-很有爱【天浩盛世】【WAV+CUE】
- 林俊吉.2012-将你惜命命【美华】【WAV+CUE】
- 晓雅《分享》DTS-WAV
- 黑鸭子2008-飞歌[首版][WAV+CUE]
- 黄乙玲1989-水泼落地难收回[日本天龙版][WAV+CUE]
- 周深《反深代词》[先听版][FLAC/分轨][310.97MB]
- 姜育恒1984《什么时候·串起又散落》台湾复刻版[WAV+CUE][1G]
- 那英《如今》引进版[WAV+CUE][1G]
- 蔡幸娟.1991-真的让我爱你吗【飞碟】【WAV+CUE】
- 群星.2024-好团圆电视剧原声带【TME】【FLAC分轨】