思想:验证就是后端随机生成,前端输入验证

           随机生成的验证码,存入到session中,和前端输入的做比较(session是客户端和服务端的会话,该信息存放在服务端)

验证码是现在必不可少的一个小功能,可以放爆破,防垃圾请求,总之还是有一定约束力的

SpringMVC实现验证码功能主要是提供一个URL请求,该请求对应的方法可以生成一张验证码图片,然后把该验证码数值存入session中,再把图片显示到界面,这样来实现验证码的验证.

1.生成验证码(也可以使用BufferedImage)

生成验证码主要使用awt的几个类,详情可以看代码注释,一共8个步骤,一步一步画出验证码

/**
 * 控制验证码的controller
 */
@Controller
public class CodeController {
    private int width = 90;//验证码宽度
    private int height = 40;//验证码高度
    private int codeCount = 4;//验证码个数
    private int lineCount = 19;//混淆线个数

    char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
            'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
            'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

    /**
     * 具体获取验证码的方法
     * @param time  time为时戳,这样的话可以避免浏览器缓存验证码
     * @throws IOException
     */
    @RequestMapping(value = "/code/{time}",method = RequestMethod.GET)
    public void getCode(@PathVariable("time") String time, HttpServletRequest request,
                        HttpServletResponse response) throws IOException{
        //定义随机数类
        Random r = new Random();
        //定义存储验证码的类
        StringBuilder builderCode = new StringBuilder();
        //定义画布
        BufferedImage buffImg = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        //得到画笔
        Graphics g = buffImg.getGraphics();
        //1.设置颜色,画边框
        g.setColor(Color.black);
        g.drawRect(0,0,width,height);
        //2.设置颜色,填充内部
        g.setColor(Color.white);
        g.fillRect(1,1,width-2,height-2);
        //3.设置干扰线
        g.setColor(Color.gray);
        for (int i = 0; i < lineCount; i++) {
            g.drawLine(r.nextInt(width),r.nextInt(width),r.nextInt(width),r.nextInt(width));
        }
        //4.设置验证码
        g.setColor(Color.blue);
        //4.1设置验证码字体
        g.setFont(new Font("宋体",Font.BOLD|Font.ITALIC,15));
        for (int i = 0; i < codeCount; i++) {
            char c = codeSequence[r.nextInt(codeSequence.length)];
            builderCode.append(c);
            g.drawString(c+"",15*(i+1),15);
        }
        //5.输出到屏幕
        ServletOutputStream sos = response.getOutputStream();
        ImageIO.write(buffImg,"png",sos);
        //6.保存到session中
        HttpSession session = request.getSession();
        session.setAttribute("codeValidate",builderCode.toString());
        //7.禁止图像缓存。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/png");
        //8.关闭sos
        sos.close();
    }
}

测试下生成的验证码

java网页验证码 java web验证码功能_java网页验证码

总体步骤如下,你想更改验证码样式就在上面那个controller中来更改

2.登录验证

在登录的基础上加上验证码功能,因为在生成验证码的时候,已经在session中存储了验证码,因此提交到服务器的验证码和session中的进行对比,这个对比应该不区分大小写,对比正确可以登录,失败则提示验证码错误

//首先是页面,这里使用img来承载验证码,注意img的请求,为你生成验证码的那个请求,同时onclick="changeUrl()"是用来点击改变验证码的一个js方法,后面会叙述

<tr>
  <td class="text-right"><strong>验证码:</strong>  </td>
  <td><input type="text" class="form-control" required name="codevalidate" style="width: 40%;display: inline">
      <img id="codevalidate" src="/code/<%=new Date().getTime()%>" width="90" height="30" style="margin-left: 10px" onclick="changeUrl()">
  </td>
</tr>

然后服务器端进行验证:

/**
     * 用户登录控制
     * @param user
     * @param attr 重定向传参数
     * @param session
     * @return
     */
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(User user,String codevalidate, RedirectAttributes attr, HttpSession session, HttpServletResponse response) throws IOException {
        if (user.getUsername() == null || user.getPassword() == null){
            attr.addFlashAttribute("error","请输入用户名或密码");
            return "redirect:/login";
        }
        //去掉空格
        user.setUsername(user.getUsername().trim());
        user.setPassword(user.getPassword().trim());
        //添加到要显示的信息中
        attr.addFlashAttribute("username",user.getUsername().trim());
        //验证码验证
        String code = (String) session.getAttribute("codeValidate");
        if (codevalidate == null || !codevalidate.equalsIgnoreCase(code)){
            attr.addFlashAttribute("error","验证码错误");
            return "redirect:/login";
        }
        //用户名密码错误
        user.setPassword(DecriptUtil.SHA1(user.getPassword().trim()));
        user = userDao.findUserByLogin(user);
        if (user == null){
            attr.addFlashAttribute("error","用户名或密码错误");
            return "redirect:/login";
        }
        //登录成功加入session
        session.setAttribute("userLogin",user);
        //更新登录时间
        userDao.updateDateById(user.getId());
        //跳转到用户主页
        return "redirect:/user/"+user.getId();
    }

3.点击验证码切换

切换的原理是更改img标签的src链接,注意这个链接要加上时戳,不然浏览器会缓存图片,导致没法刷新图片

function changeUrl() {
            var url = $("#codevalidate").prop('src');
            url = url.substr(0,url.lastIndexOf('/')+1);
            url = url + (new Date()).valueOf();
            $("#codevalidate").prop('src',url);
        }

最终效果如下:

java网页验证码 java web验证码功能_用户名_02

登录失败则提示失败信息:

java网页验证码 java web验证码功能_Image_03