ssm框架下手机验证码、图片验证码的实现

手机验证码

第一步:网上找一个第三方短信接口平台,大多数这样的平台都会有免费试用的通知短信。我这里用的是秒滴科技,注册个账号,赠送200条短信,足够项目练手使用了。

第二步:去用户中心查看TOKEN(ACCOUNT SID和AUTH TOKEN的值很重要,后面写代码要用到)。
这里写图片描述
第三步:查看API文档,这里要用到官方提供的接口。
这里写图片描述
第四步:在配置管理里面新建模板,模板审核通过后即可启用。
这里写图片描述
第五步:引入jar包,该功能只用了一个jar包
这里写图片描述
第六步:编写代码
首先是jsp界面,这里我把整个页面都copy下来了,页面功能只有手机验证码和图片验证码。

<%@ 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%>">
    <meta charset="UTF-8">
    <title>test</title>
    <link rel="stylesheet" href="css/bootstrap.min.css"/>
    <link rel="stylesheet" href="css/bootstrap-datetimepicker.min.css"/>
    <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>
    <style type="text/css">
        #login{ width:450px; height:100px; margin:50px auto;}
        #btn{ margin-left:100px; margin-top:-25px; width: 120px;height: 25px; font-size: 11px; }
        body{ background-color: #ecfcf9;}
    </style>
</head>
<!-- 图片验证码  -->
<script src="js/gVerify.js"></script>
<script>
    $(function(){
        var verifyCode = new GVerify("v_container");
        document.getElementById("code_input").onblur = function(){
            var res = verifyCode.validate(document.getElementById("code_input").value);
            if(res){
                alert("验证正确");
            }else{
                alert("验证码错误");
            }
        }
    })

</script>
<!-- 发送短信验证码倒计时-->
<script type="text/javascript">
    var InterValObj; //timer变量,控制时间
    var count = 30; //间隔函数,1秒执行
    var curCount;//当前剩余秒数
    function sendMessage(){curCount = count;
        $("#btn").attr("disabled", "true");
        $("#btn").val(curCount + "秒后可重新发送");
        InterValObj = window.setInterval(SetRemainTime, 1000); //启动计时器,1秒执行一次请求后台发送验证码 TODO
    }
    //timer处理函数
    function SetRemainTime() {
        if (curCount == 0) {
            window.clearInterval(InterValObj);//停止计时器
            $("#btn").removeAttr("disabled");//启用按钮
            $("#btn").val("重新发送验证码");
        }
        else {
            curCount--;
            $("#btn").val(curCount + "秒后可重新发送");
        }
    }
</script>
<body>
       <div class="container">
           <div  id="login">
           <form class="form-horizontal" role="form">
                <div class="form-group">
                   <label class="col-sm-2 control-label">验证码</label>
                   <div class="col-sm-5">
                       <input type="text" class="form-control" id="code_input" placeholder="请输入验证码"  required autofocus>
                       <span id="v_container"></span>
                   </div>
               </div>
               <div class="form-group" style="position: relative;top:50px;">
                   <label class="col-sm-2 control-label">手机号</label>
                   <div class="col-sm-5">
                       <input type="text" class="form-control" id="phone" name="phone" placeholder="请输入您的手机号"  required autofocus>

                   </div>
               </div>
               <div class="form-group" style="position: relative;top:50px;">
                   <label class="col-sm-2 control-label">验证码</label>
                   <div class="col-sm-3">
                       <input type="code" class="form-control" id="code" name="code" placeholder="验证码" required>
                       <input class="btn btn-default" id="btn" name="btn" value="发送验证码" onclick="sendMessage()" />
                   </div>
               </div>
               <div class="form-group" style="position: relative;top:50px;">
                   <div class="col-sm-offset-2 col-sm-10">
                       <button type="button" class="btn btn-info" id="lo">验证</button>
                   </div>
               </div>
           </form>
       </div>
       </div>
</body>
<!-- 发送短信验证码并验证  -->
<script type="text/javascript">
    var sms="";
    $("#btn").click(function(){
        var phone=$("#phone").val();
        if(phone!="")
        {
            $.ajax({
                url:"http://localhost:8866/TestCode/sendSMS.do",
                type:"post",
                data:{"phone":phone},
                dataType:"json",
                success:function(result){
                    if(result.status==1){
                        sms=result.data;
                    }
                }
            });

        }else{
             alert("请输入手机号");
            return false;
        }

    });
    $("#lo").click(function(){
        var code=$("#code").val();
        if(code==""){
            alert("请输入验证码");
        }else{
            if(sms==code){
                window.location.href="http://localhost:8866/TestCode/jsp/success.jsp";
            }else{
                alert("验证码错误");
            };
        };
    });
</script>
</html>

其次是发送短信的核心代码部分

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.json.JSONObject;

public class GetMessageCode {
    private static final String QUERY_PATH="https://api.miaodiyun.com/20150822/industrySMS/sendSMS";
    private static final String ACCOUNT_SID="上面提到的ACCOUNT SID";
    private static final String AUTH_TOKEN="上面提到的AUTH TOKEN";


    //根据相应的手机号发送验证码
    public static String getCode(String phone){
        String rod=smsCode();
        String timestamp=getTimestamp();
        String sig=getMD5(ACCOUNT_SID,AUTH_TOKEN,timestamp);
        String tamp="【xxxx】尊敬的用户,您的验证码为"+rod+",如非本人操作请忽略此短信。";//这里一定要与新建模板中的短信内容一致,一个空格都不能多,否者短信打死都发不过去哦
        OutputStreamWriter out=null;
        BufferedReader br=null;
        StringBuilder result=new StringBuilder();
        try {
            URL url=new URL(QUERY_PATH);
            HttpURLConnection connection=(HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setDoInput(true);//设置是否允许数据写入
            connection.setDoOutput(true);//设置是否允许参数数据输出
            connection.setConnectTimeout(5000);//设置链接响应时间
            connection.setReadTimeout(10000);//设置参数读取时间
            connection.setRequestProperty("Content-type","application/x-www-form-urlencoded");          
            //提交请求
            out=new OutputStreamWriter(connection.getOutputStream(),"UTF-8");
            String args=getQueryArgs(ACCOUNT_SID, tamp, phone, timestamp, sig, "JSON");
            out.write(args);
            out.flush();
            //读取返回参数

            br=new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));
            String temp="";
            while((temp=br.readLine())!=null){
                result.append(temp);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        JSONObject json=new JSONObject(result.toString());
        String respCode=json.getString("respCode");
        String defaultRespCode="00000";
        if(defaultRespCode.equals(respCode)){
             return rod;
        }else{
            return defaultRespCode;         
        }
    }
    //定义一个请求参数拼接方法
    public static String getQueryArgs(String accountSid,String smsContent,String to,String timestamp,String sig,String respDataType){
        return "accountSid="+accountSid+"&smsContent="+smsContent+"&to="+to+"&timestamp="+timestamp+"&sig="+sig+"&respDataType="+respDataType;
    }
    //获取时间戳
    public static String getTimestamp(){
        return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
    }
    //sing签名
    public static String getMD5(String sid,String token,String timestamp){

        StringBuilder result=new StringBuilder();
        String source=sid+token+timestamp;
        //获取某个类的实例
                try {                   
                   MessageDigest digest=MessageDigest.getInstance("MD5");
                   //要进行加密的东西
                   byte[] bytes=digest.digest(source.getBytes());
                   for(byte b:bytes){
                       String hex=Integer.toHexString(b&0xff);
                       if(hex.length()==1){
                           result.append("0"+hex);
                       }else{
                           result.append(hex);
                       }
                   }
                } catch (NoSuchAlgorithmException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 


        return result.toString();
    }
    //创建验证码
    public static String smsCode(){
        String random=(int)((Math.random()*9+1)*100000)+"";     
        return random;
    }
}

接着是controller层

@Controller
public class CodeController {

    @Resource
    private ReturnContant returnContant;
    /**
     * 根据获取到的手机号发送验证码
     * @param request
     * @param phone 获取的手机号码
     * @return
     */
    @RequestMapping(value="/sendSMS.do",method=RequestMethod.POST)
    public @ResponseBody ReturnContant sendSMS(HttpServletRequest request,String phone){
        //根据获取到的手机号发送验证码
        String code=GetMessageCode.getCode(phone); 
        returnContant.setStatus(1);
        returnContant.setData(code);
        return returnContant;
    }
}   

这里的ReturnContant是供ajax使用的封装类

@Component
public class ReturnContant  implements Serializable{

        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        private int status;
        private String msg;
        private Object data;
        public int getStatus() {
            return status;
        }
        public void setStatus(int status) {
            this.status = status;
        }
        public String getMsg() {
            return msg;
        }
        public void setMsg(String msg) {
            this.msg = msg;
        }
        public Object getData() {
            return data;
        }
        public void setData(Object data) {
            this.data = data;
        }       
}

到这里手机验证码就可以发送成功了,下面上图
这里写图片描述
这里写图片描述
最后就是验证手机验证码正确与否了,可详见上面的jsp页面。

图片验证码

这个利用的是jquery插件,上面的就是jsp界面引入了gVerify.js,里面的具体代码如下:

!(function(window, document) {
    function GVerify(options) { //创建一个图形验证码对象,接收options对象为参数
        this.options = { //默认options参数值
            id: "", //容器Id
            canvasId: "verifyCanvas", //canvas的ID
            width: "100", //默认canvas宽度
            height: "40", //默认canvas高度
            type: "blend", //图形验证码默认类型blend:数字字母混合类型、number:纯数字、letter:纯字母
            code: ""
        }

        if(Object.prototype.toString.call(options) == "[object Object]"){//判断传入参数类型
            for(var i in options) { //根据传入的参数,修改默认参数值
                this.options[i] = options[i];
            }
        }else{
            this.options.id = options;
        }

        this.options.numArr = "0,1,2,3,4,5,6,7,8,9".split(",");
        this.options.letterArr = getAllLetter();

        this._init();
        this.refresh();
    }

    GVerify.prototype = {
        /**版本号**/
        version: '1.0.0',

        /**初始化方法**/
        _init: function() {
            var con = document.getElementById(this.options.id);
            var canvas = document.createElement("canvas");
            this.options.width = con.offsetWidth > 0 ? con.offsetWidth : "100";
            this.options.height = con.offsetHeight > 0 ? con.offsetHeight : "40";
            canvas.id = this.options.canvasId;
            canvas.width = this.options.width;
            canvas.height = this.options.height;
            canvas.style.cursor = "pointer";
            canvas.innerHTML = "您的浏览器版本不支持canvas";
            con.appendChild(canvas);
            var parent = this;
            canvas.onclick = function(){
                parent.refresh();
            }
        },

        /**生成验证码**/
        refresh: function() {
            this.options.code = "";
            var canvas = document.getElementById(this.options.canvasId);
            if(canvas.getContext) {
                var ctx = canvas.getContext('2d');
            }else{
                return;
            }

            ctx.textBaseline = "middle";

            ctx.fillStyle = randomColor(180, 240);
            ctx.fillRect(0, 0, this.options.width, this.options.height);

            if(this.options.type == "blend") { //判断验证码类型
                var txtArr = this.options.numArr.concat(this.options.letterArr);
            } else if(this.options.type == "number") {
                var txtArr = this.options.numArr;
            } else {
                var txtArr = this.options.letterArr;
            }

            for(var i = 1; i <= 4; i++) {
                var txt = txtArr[randomNum(0, txtArr.length)];
                this.options.code += txt;
                ctx.font = randomNum(this.options.height/2, this.options.height) + 'px SimHei'; //随机生成字体大小
                ctx.fillStyle = randomColor(50, 160); //随机生成字体颜色        
                ctx.shadowOffsetX = randomNum(-3, 3);
                ctx.shadowOffsetY = randomNum(-3, 3);
                ctx.shadowBlur = randomNum(-3, 3);
                ctx.shadowColor = "rgba(0, 0, 0, 0.3)";
                var x = this.options.width / 5 * i;
                var y = this.options.height / 2;
                var deg = randomNum(-30, 30);
                /**设置旋转角度和坐标原点**/
                ctx.translate(x, y);
                ctx.rotate(deg * Math.PI / 180);
                ctx.fillText(txt, 0, 0);
                /**恢复旋转角度和坐标原点**/
                ctx.rotate(-deg * Math.PI / 180);
                ctx.translate(-x, -y);
            }
            /**绘制干扰线**//*
            for(var i = 0; i < 4; i++) {
                ctx.strokeStyle = randomColor(40, 180);
                ctx.beginPath();
                ctx.moveTo(randomNum(0, this.options.width), randomNum(0, this.options.height));
                ctx.lineTo(randomNum(0, this.options.width), randomNum(0, this.options.height));
                ctx.stroke();
            }*/
            /**绘制干扰点**/
            for(var i = 0; i < this.options.width/4; i++) {
                ctx.fillStyle = randomColor(0, 255);
                ctx.beginPath();
                ctx.arc(randomNum(0, this.options.width), randomNum(0, this.options.height), 1, 0, 2 * Math.PI);
                ctx.fill();
            }
        },

        /**验证验证码**/
        validate: function(code){
            var code = code.toLowerCase();
            var v_code = this.options.code.toLowerCase();
            console.log(v_code);
            if(code == v_code){
                return true;
            }else{
                this.refresh();
                return false;
            }
        }
    }
    /**生成字母数组**/
    function getAllLetter() {
        var letterStr = "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,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";
        return letterStr.split(",");
    }
    /**生成一个随机数**/
    function randomNum(min, max) {
        return Math.floor(Math.random() * (max - min) + min);
    }
    /**生成一个随机色**/
    function randomColor(min, max) {
        var r = randomNum(min, max);
        var g = randomNum(min, max);
        var b = randomNum(min, max);
        return "rgb(" + r + "," + g + "," + b + ")";
    }
    window.GVerify = GVerify;
})(window, document);

大致效果就是这样,当然是有那么点丑
这里写图片描述
搞了这么久终于出来了,你以为我很开心吗???
不,领导开会说:“这是针对国外的项目,还是用邮件吧(更何况短信验证码要钱)。”
噢,所以下面我要写注册界面邮件验证了

  • 13
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
SSM框架实现验证码可以通过以下步骤: 1. 在Spring MVC的Controller,定义一个方法用于生成验证码图片,并将生成的验证码字符串存储到session。 ```java @RequestMapping("/getVerifyCodeImage") public void getVerifyCodeImage(HttpServletRequest request, HttpServletResponse response) throws Exception { // 生成验证码 String verifyCode = VerifyCodeUtils.generateVerifyCode(4); // 将验证码存入session request.getSession().setAttribute("verifyCode", verifyCode); // 生成验证码图片 BufferedImage image = VerifyCodeUtils.generateImage(verifyCode, 100, 40); // 将验证码图片输出给客户端 ImageIO.write(image, "JPEG", response.getOutputStream()); } ``` 2. 在前端页面使用AJAX请求获取验证码图片,并将图片显示在页面上。 ```javascript $.ajax({ url: "/getVerifyCodeImage", type: "GET", success: function(data) { $("#verifyCodeImage").attr("src", "data:image/jpeg;base64," + data); } }); ``` 3. 在后端Controller,验证用户输入的验证码是否正确。 ```java @RequestMapping("/login") public String login(HttpServletRequest request, HttpServletResponse response) throws Exception { String username = request.getParameter("username"); String password = request.getParameter("password"); String verifyCode = request.getParameter("verifyCode"); String sessionVerifyCode = (String) request.getSession().getAttribute("verifyCode"); if (!verifyCode.equalsIgnoreCase(sessionVerifyCode)) { request.setAttribute("errorMsg", "验证码错误"); return "login"; } // 验证用户名和密码 // ... } ``` 通过以上步骤,就可以在SSM框架实现验证码的功能。需要注意的是,生成验证码的工具类VerifyCodeUtils需要自行实现或引入第三方库。在实现过程,还要注意验证码的安全性,避免机器自动识别验证码的攻击。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值