登录验证码demo-java

在一些类似于管理系统的项目中,我们在登录时经常会用到图片验证码。这里把我自己写的一个小系统(后台是java语言)的验证码部分摘出来。

总体思路是后端有一个生成验证码图片的接口,把验证码图片写入浏览器,前端页面在img标签里的src属性里填写后端生成验证码图片的接口地址即可。

1、java部分-CaptchaController.java

我这里是把后端生成的验证码生成图片返回给浏览器时,同时存入到了数据库中,前端登录时,后端根据前端输入的验证码和数据库中的验证码作对比,来判断是否可以登录。

package com.lin.controller;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
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.lin.domain.Captcha;
import com.lin.service.SysUserService;


/**
 * 验证码-controller
 * @author libo
 */
@Controller
@RequestMapping("/captcha")
public class CaptchaController {
    
    @Autowired
    private SysUserService uService;
    
    /**
     * 随机字符字典
     */
    private static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8',
        '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
        'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm',
        'n', 'p', 'q', 'r', 's', 't', 'u' ,'v', 'w', 'x', 'y', 'z'};
    
    /**
     * 随机数
     */
    private static Random random = new Random();
    
    /**
     * 获取4位随机数
     * @return
     */
    private static String getRandomString() {
        StringBuffer buffer = new StringBuffer();
        for(int i = 0; i < 4; i++) {
            buffer.append(CHARS[random.nextInt(CHARS.length)]);
        }
        return buffer.toString();
    }
    
    /**
     * 获取随机数颜色
     * @return
     */
    private static Color getRandomColor() {
        return new Color(random.nextInt(255),random.nextInt(255), random.nextInt(255));
    }
    
    /**
     * 返回某颜色的反色
     * @param c
     * @return
     */
    private static Color getReverseColor(Color c) {
        return new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c.getBlue());
    }
    
    /**
     * 生成验证码
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value="/getCaptcha.do", method=RequestMethod.GET)
    public void outputCaptcha(HttpServletRequest request, HttpServletResponse response, String rad)
            throws ServletException, IOException {

        // 设置页面不缓存
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");

        String randomString = getRandomString(); //生成的验证码
        
        Captcha c = new Captcha();
        c.setCaptchaId(rad);
        c.setCaptcha(randomString.toUpperCase());
        Integer id = uService.saveCaptcha(c);//保存验证码到数据库中
        if(id > 0){    //验证码保存成功
            
        }else{    //验证码保存失败
            return;
        }
        
        int width = 100;    //验证码图像的宽度
        int height = 34;    //验证码图像的高度

        // 在内存中创建图象
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bi.createGraphics();
        for(int i=0; i<randomString.length(); i++){
            Color color = getRandomColor();
            Color reverse = getReverseColor(color);
            g.setColor(color);    //设置字体颜色
            g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 25));    //设置字体样式
            g.fillRect(0, 0, width, height);
            g.setColor(reverse);
            g.drawString(randomString, 18, 25);
        }
        //随机生成一些点
        for (int i = 0, n = random.nextInt(100); i < n; i++) {
            g.drawRect(random.nextInt(width), random.nextInt(height), 1, 1);
        }
        // 随机产生干扰线,使图象中的认证码不易被其它程序探测到
        for (int i = 0; i < 10; i++) {
            g.setColor(getRandomColor());
            final int x = random.nextInt(width-1); // 保证画在边框之内
            final int y = random.nextInt(height-1);
            final int xl = random.nextInt(width);
            final int yl = random.nextInt(height);
            g.drawLine(x, y, x + xl, y + yl);
        }
        g.dispose();    //图像生效
        ImageIO.write(bi, "JPEG", response.getOutputStream());    //输出图片到页面
        
    }
    
    
}

2、html部分-login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>后台管理系统登录</title>
    <link rel="stylesheet" href="/common/css/index.css">
    <script src="/scripts/apiConfig.js"></script>
    <script src="/lib/jquery/jquery.min.js"></script>
    <script src="/lib/aes/aes.min.js"></script>
    <script src="/common/js/utils.js"></script>
</head>
<body>
    <div class="layout">
        <div class="top-name">后台管理系统
            <span>Background Management System</span>
        </div>
        <div class="main">
            <div class="item">
                <label style="word-spacing: 10px;">邮 箱:</label>
                <input type="text" id="loginEmail" class="f-s-14" autocomplete="off" placeholder="请输入邮箱">
                <span class="err-tip" id="tipLEmail" ng-class="m-l-15"></span>
            </div>
            <div class="item">
                <label style="word-spacing: 10px;">密 码:</label>
                <input type="password" id="loginPwd" class="f-s-14" autocomplete="off" placeholder="请输入密码">
                <span class="err-tip " id="tipLPwd" ng-class="m-l-15"></span>
            </div>
            <div class="item clearfix">
                <label>验证码:</label>
                <input type="text" id="captcha" class="f-s-14" placeholder="请输入验证码" style="width: 200px;">
                <a href="javascript:void(0);" onclick="updateCaptcha()" style="height: 36px;width: 100px;float: right;">
                    <img src="" alt="" id="captcha_img">
                </a>
                <span class="err-tip" id="tipCaptcha" ng-class="m-l-15"></span>
            </div>
            <div style="text-align: center;margin-top: -10px;height: 20px;margin-bottom: 5px;">
                <span class="err-tip" id="error" ng-class="m-l-15" style="font-size: 14px;"></span>
            </div>
            <div class="item">
                <button type="button" class="submit" id="submit" style="outline: none;">登 录</button>
            </div>
        </div>
    </div>
</body>
<script>

    //更新验证码
    var random = '';
    function updateCaptcha() {
        random = new Date().getTime()+''+Math.floor(Math.random() * Math.pow(10, 8));
        $('#captcha_img').attr('src', hostObj.host+'/captcha/getCaptcha.do?rad='+random);
    }
    $(function () {
        //页面加载的时候就获取验证码
        updateCaptcha();

        $('#loginEmail').blur(function () {
            checkLoginEmail();
        });
        $('#loginPwd').blur(function () {
            checkLoginPwd();
        });
        $('#captcha').blur(function () {
            checkCaptcha();
        });

        $("#submit").click(function() {
            var flag1 = checkLoginEmail();
            var flag2 = checkLoginPwd();
            var flag3 = checkCaptcha();
            if(!flag1 || !flag2 || !flag3){
                return;
            }
            $.ajax({
                type:'post',
                url: hostObj.host+'/sysUser/login.do',
                dataType:"json",
                data:{
                    loginEmail:$("#loginEmail").val(),
                    loginPwd:encrypt($("#loginPwd").val()),
                    captcha: $('#captcha').val(),
                    captchaId: random
                },
                success:function(res) {
                    if(res.success == 1){
                        var user = {
                            id: res.data.id,
                            email: res.data.email,
                            createTime: res.data.createTime.substring(0,19),
                            lastLoginTime: res.data.lastLoginTime.substring(0,19),
                            status: res.data.status
                        }
                        window.location.href = "main.html";
                    }else{
                        $('#error').html(res.error.msg);
                        if(res.error.code == 4000){
                            $('#captcha').focus();
                        }
                    }
                },
                error:function(res){
                    $('#error').html('系统错误!');
                }
            });
        });

        function checkLoginEmail() {
            if($.trim($('#loginEmail').val()) == ''){
                $('#tipLEmail').html('请输入邮箱');
                return false;
            }else{
                $('#tipLEmail').html('');
                return true;
            }
        }

        function checkLoginPwd() {
            if($.trim($('#loginPwd').val()) == ''){
                $('#tipLPwd').html('请输入登录密码');
                return false;
            }else{
                $('#tipLPwd').html('');
                return true;
            }
        }

        function checkCaptcha() {
            if($.trim($('#captcha').val()) == ''){
                $('#tipCaptcha').html('请输入验证码');
                return false;
            }else{
                $('#tipCaptcha').html('');
                return true;
            }
        }</script>
</html>

3、效果

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ml

caffe源码学习之Proto数据格式【1】

前言:   由于业务需要,接触caffe已经有接近半年,一直忙着阅读各种论文,重现大大小小的模型. 期间也总结过一些caffe源码学习笔记,断断续续,这次打算系...

69180
来自专栏牛客网

网易一面面经

自我介绍 TCP三次握手和四次挥手的过程 为什么是三次握手 JDK动态代理 如果没有实现接口使用什么?(CGLIB) NIO和BIO区别 HashMap Con...

44190
来自专栏移动开发面面观

ProgressiveJpeg介绍与在Android中的使用

27340
来自专栏Seebug漏洞平台

“盲”逆向:iOS 应用 Blind 寻踪

原文:https://exceptionlevelone.blogspot.tw/2017/10/blind-reversing.html 译者:hello19...

518140
来自专栏小巫技术博客

Retrofit2 &amp; RxJava2实现单文件和多文件上传

66240
来自专栏一个会写诗的程序员的博客

第13章 Kotlin 集成 SpringBoot 服务端开发(2)

其中,ON DUPLICATE KEY UPDATE 这句表明当遇到重复的键值的时候,执行更新 gmt_modified = now() 的操作。这里nativ...

13610
来自专栏IT笔记

JAVA实现微信退款报错unexpected end of file from server

前几天做了微信扫码支付,同事说把退款接口也做了吧,然后就根据申请退款文档,把支付的方法拿过来用了,结果抛出了这样一个问题 unexpected end of f...

43390
来自专栏wannshan(javaer,RPC)

ConcurrentHashMap 锁分段 源码分析

看ConcurrentHashMap下几个属性: /** * The default concurrency level for this table...

42660
来自专栏颇忒脱的技术博客

Servlet 3.1 Async IO分析

Servlet Async Processing提供了一种异步请求处理的手段(见我的另一篇文章Servlet 3.0 异步处理详解),能够让你将Http thr...

16830
来自专栏芋道源码1024

面试问烂的 Spring MVC 过程

来源:https://www.jianshu.com/p/e18fd44964eb

20130

扫码关注云+社区

领取腾讯云代金券