- 论坛徽章:
- 0
|
大多网站登录时需要输入一个验证码,这主要是基于安全性方面的考虑。在这里将详细的说明一下验证码的生成和验证。
首先是java文件(这段java主要写了验证码图片的生成及各种特效,比如旋转、干扰线、噪点等,并将其用流的方式传到前端页面):- package com.servlet;
- import java.awt.BasicStroke;
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.Stroke;
- import java.awt.image.BufferedImage;
- import java.io.IOException;
- import java.util.Random;
- import javax.imageio.ImageIO;
- import javax.servlet.ServletException;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- public class ImageServlet extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doPost(request, response);
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- int width=100;//验证码图片宽度
- int height=40;//验证码图片高度
- BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR);
- Graphics g=image.getGraphics();
- Graphics2D g2d = (Graphics2D) g;
- Random random=new Random();
- g.setColor(Color.white);//背景颜色(或getRandColor(160,250))
- g.fillRect(0, 0, width, height);//画背景
- //g.setColor(getRandColor(0,255));//边框颜色
- // g.drawRect(0, 0, width-1, height-1);//画边框
- // 随机产生20条干扰线,使图象中的认证码不易被其它程序探测到
- g.setColor(getRandColor(160,200));
- //Stroke stroke=new BasicStroke(3.0f);//设置线宽为3.0
- for(int i=0;i<20;i++){
- int x=random.nextInt(width);
- int y=random.nextInt(height);
- int x1=random.nextInt(20);
- int y1=random.nextInt(20);
- g.drawLine(x,y,x+x1,y+y1);
- //g2d.setStroke(stroke);
- }
- // 随机产生20点,使图象中的认证码不易被其它程序探测到
- g.setColor(getRandColor(160,200));
- for(int i=0;i<20;i++){
- int x=random.nextInt(width);
- int y=random.nextInt(height);
- g.drawLine(x, y, x, y);
- }
- //随机生成不同的字体、字体样式和字体大小
- String[] fontName = {"微软雅黑","黑体","Georgia","Verdana","Arial","Comic Sans MS","Lucida Console"};
- int [] fontEffect = {Font.PLAIN, Font.ITALIC, Font.BOLD};
- int [] fontSize = {28, 30, 32, 26};
- Font[] fonts = new Font[fontName.length*fontEffect.length*fontSize.length];
- int fontsIndex=0;
- for(String str: fontName){
- for(int effect: fontEffect){
- for(int size : fontSize){
- Font font = new Font(str, effect, size);
- fonts[fontsIndex]=font;
- fontsIndex = fontsIndex +1;
- }
- }
- }
- String s="abcdefghijknpqrstuvxyzABCDEFGHJKLNPQRSTUVXYZ23456789"; // 设置备选验证码
- String sRand="";
- // 用随机产生的颜色将验证码绘制到图像中。
- int length = 4; // 设置默认生成4个验证码
- for(int i=0;i<length;i++){
- g.setColor(new Color(20+random.nextInt(110), 20+random.nextInt(110), 20+random.nextInt(110))); // 生成随机颜色(因为是做前景,所以偏深)
- g.setFont(fonts[random.nextInt(fonts.length)]); //调用上方的随机字体
- String ch=String.valueOf(s.charAt(random.nextInt(s.length())));
- //设置字体旋转
- int zhuan = random.nextInt(20);
- int fzhuan = -random.nextInt(20);
- g2d.rotate(Math.toRadians(zhuan),25*(i-1),20); /// 坐标系顺时针转
- g2d.rotate(Math.toRadians(fzhuan),25*(i-1),20); /// 坐标系逆时针转
-
- sRand+=ch;
- g.drawString(ch, 18 * i + 15, 30); //将认证码用 drawString 函数显示到图象里
- g2d.rotate(Math.toRadians(-1*zhuan),25*(i-1),20);
- g2d.rotate(Math.toRadians(-1*fzhuan),25*(i-1),20);
- }
- //将生成的字符串存储在session中
- HttpSession session=request.getSession();
-
- //在认证码的上端画一条不规则的线
- int visit[] = new int[6];
- for (int i = 0; i < visit.length; i++) {
- visit[i] = 1 + (int) (Math.random() * 10);
- }
- int visitValue = 0;
- g.setColor(Color.BLACK);
- int drawHigh[] = new int[6];
- int drawwidth[] = new int[6];
- //折点坐标
- for (int i = 0; i < 6; i++) {
- drawHigh[i] = 40 - (int) (Math.ceil(visit[i] * 3.8));
- drawwidth[i] = 5 + i * 17;
- }
- //g2d.setXORMode(Color.WHITE);
- g2d.setStroke(new BasicStroke(3.0f)); //折线粗细
- g2d.setPaint(Color.gray);//折线的颜色
- g2d.drawPolyline(drawwidth, drawHigh, 6); //画折线
-
- session.setAttribute("checkCode", sRand);
- g.dispose();//图像生效
- //禁止图像缓存
- response.setHeader("Pragma", "No-cache");
- response.setHeader("Cache-Control", "no-cache");
- response.setDateHeader("Expires", 0);
- response.setContentType("image/jpeg");
- //创建二进制的输出流
- ServletOutputStream sos=response.getOutputStream();
- // 将图像输出到Servlet输出流中。
- ImageIO.write(image, "jpeg", sos);
- sos.flush();
- sos.close();
- }
- public Color getRandColor(int lower,int upper){
- Random random = new Random();
- if(upper>255)
- upper=255;
- if(upper<1)
- upper=1;
- if(lower<1)
- lower=1;
- if(lower>255)
- lower=255;
- int r=lower+random.nextInt(upper-lower);
- int g=lower+random.nextInt(upper-lower);
- int b=lower+random.nextInt(upper-lower);
- return new Color(r,g,b);
- }
- }
复制代码 然后是前端的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">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>验证码的生成和验证</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
- <script type="text/javascript" language="javascript">
- function changeImg(){
- $("#img").attr("src", "ImageServlet?time="+new Date());
- }
- $(function(){
- $("#button").click(function(){
- changeImg();
- var v_inputCode = document.getElementById("validate").value.toLowerCase();
- if(v_inputCode == ""){
- alert("请输入验证码");
- }else{
- $.post("<%=basePath%>test.htm",{inputCode:v_inputCode},
- function(data){
- data = $.parseJSON(data);
- if(data.test== 1){
- alert("请输入正确的验证码");
- }else{
- alert("验证码输入正确");
- location.href='../jsp/index.html';//跳转页面
- }
- });
- }
- });
- });
- </script>
- </head>
-
- <body>
- <form action="#">
- <table>
- <caption>验证码测试</caption>
- <tr>
- <td>验证码</td>
- <td colspan="2">
- <input type="text" id="validate" />
- <a href='javascript:changeImg();' title="看不清请点我" >
- <img id="img" align="middle" src="ImageServlet" />
- </a>
- </td>
- </tr>
- <tr>
- <td colspan="2"><input id="button" type="button" value="查 询" /></td>
- </tr>
- </table>
- </form>
- </body>
- </html>
复制代码 最后是验证(这里主要是将前端传入的用户输入的验证码与session中的验证码作对比,再返回给前端):- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import javax.annotation.Resource;
- import javax.mail.Session;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import net.sf.json.util.NewBeanInstanceStrategy;
- import org.omg.CORBA.PUBLIC_MEMBER;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseBody;
- import com.util.StringUtil;
- @Controller
- public class TestController {
- @Resource(name = "stringutil")
- private StringUtil stringUtil;
-
- @RequestMapping(value = "test.htm",method = RequestMethod.POST)
- public @ResponseBody Map<String, Object> querycard(HttpServletRequest request,
- HttpServletResponse response){
- Map<String, Object> result = new HashMap<String, Object>();
- String string = request.getSession().getAttribute("checkCode").toString();
- Map<String, Object> requestMap = stringUtil.getParamsForJqgrid(request);
- Map<String, Object> map = (Map<String, Object>) requestMap.get("paraMap");
- if((string.toLowerCase()).equals(map.get("inputCode").toString().toLowerCase())){//不区分大小写(将两个值都转换成小写再进行比较)
- result.put("test",0);//true
- }else {
- result.put("test",1);//false
- }
- return result;
- }
- }
复制代码 |
|