• 做在线投票防止作弊的一些体会


    前一阵子因为需要,做一个在线投票的程序,在程序发布以后,一直出现各种bug
    一开始是用Cookies做验证,客户禁用Cookies作弊,后来采取记录IP,客户端用软件速度换IP
    后来还发现一个问题,就是投票按钮可以重复提交,用户按住投票按钮不放,就可以一直刷票
    最后,还是才用Cookies验证的方法
    思路是这样的
    首先在一个页面产生一个验证码,把它记录到一个Cookies里:Response.Cookies.Add(new HttpCookie("CheckCode", checkCode));
    在投票按钮事件出发后,首先判断Response.Cookies["CheckCode"]是否==null,如果成立
    则提示用户需开启Cookies才能投票,关闭投票小窗口
    产生验证码的代码如下:
    CheckCode.aspx.cs
    private string GenerateCheckCode()
      {
       int number;
       char code;
       string checkCode = String.Empty;

       System.Random random = new Random();

       for(int i=0; i<5; i++)
       {
        number = random.Next();

        if(number % 2 == 0)
         code = (char)('0' + (char)(number % 10));
        else
         code = (char)('A' + (char)(number % 26));

        checkCode += code.ToString();
       }

       Response.Cookies.Add(new HttpCookie("CheckCode", checkCode));

       return checkCode;
      }

      private void CreateCheckCodeImage(string checkCode)
      {
       if(checkCode == null || checkCode.Trim() == String.Empty)
        return;

       System.Drawing.Bitmap image = new System.Drawing.Bitmap((int)Math.Ceiling((checkCode.Length * 12.5)), 22);
       Graphics g = Graphics.FromImage(image);

       try
       {
        //生成随机生成器
        Random random = new Random();

        //清空图片背景色
        g.Clear(Color.White);

        //画图片的背景噪音线
        for(int i=0; i<25; i++)
        {
         int x1 = random.Next(image.Width);
         int x2 = random.Next(image.Width);
         int y1 = random.Next(image.Height);
         int y2 = random.Next(image.Height);

         g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
        }

        Font font = new System.Drawing.Font("Arial", 12, (System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic));
        System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true);
        g.DrawString(checkCode, font, brush, 2, 2);

        //画图片的前景噪音点
        for(int i=0; i<100; i++)
        {
         int x = random.Next(image.Width);
         int y = random.Next(image.Height);

         image.SetPixel(x, y, Color.FromArgb(random.Next()));
        }

        //画图片的边框线
        g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);

        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
        Response.ClearContent();
        Response.ContentType = "image/Gif";
        Response.BinaryWrite(ms.ToArray());
       }
       finally
       {
        g.Dispose();
        image.Dispose();
       }
      }
     }

    在Vote.aspx里引用上页面所产生的验证码
    在登录页面中使用“<IMG>” 这个 HTML 元素来显示生成的验证码图片:<IMG src="CheckCode.aspx">
    投票按钮事件处理
    vote.aspx.cs
    private void Button1_Click(object sender, System.EventArgs e)
      {
       if(Request.Cookies["CheckCode"] == null)
       {
        Response.Write("<script language=\"JavaScript\">alert('您的浏览器设置已被禁用 Cookies,您必须设置浏览器允许使用 Cookies 选项后才能投票!');window.close();</script>");
        return;
       }
       Button1.Enabled = false;
       UpdateVote();
      }

    private void UpdateVote()
      {
       if(String.Compare(Request.Cookies["CheckCode"].Value, txtValidate.Text, true) != 0)
       {
        Response.Write(HouseBasic.ScriptAlertMsg("验证码错误,请输入正确的验证码。"));
        return;
       }
       string vote = "," + Request.QueryString["id"];
       if(Request.Cookies["Vote"]   !=   null)    
       {  
        if(Request.Cookies["Vote"]["IP"] == Request.ServerVariables["REMOTE_ADDR"] && Request.Cookies["Vote"]["ID"].IndexOf(vote) >= 0)
        {
         Response.Write("<script language=\"JavaScript\">alert('您今天已经为本选手投了一票,不能再投了哟:');window.close();</script>");
         Response.End();
        }
        vote += "," + Request.Cookies["Vote"]["ID"];
       }  
       HttpCookie cookie = new HttpCookie("Vote");
       cookie.Values.Add("IP", Request.ServerVariables["REMOTE_ADDR"]);
       cookie.Values.Add("ID", vote);
       cookie.Expires = DateTime.Now.AddDays(1);
       Response.Cookies.Add(cookie);
       //投票处理
    }
    现在还剩下防止Button按钮重复提交了
    在网上搜索了一个防止重复提交的js方法
    js.js
    function _doPostBack(){};
    if(typeof("__doPostBack")=="function")
    {
     _doPostBack=__doPostBack;
     __doPostBack=_doPostBackNew;
    }

    document.attachEvent("onmousemove",_onmousemove);
    var _isPosting=false;
    var _divMask=null;

    function _onmousemove()
    {
     if(_divMask)
     with(_divMask.runtimeStyle)
     {
      left=event.clientX+document.body.scrollLeft-4;
      top=event.clientY+document.body.scrollTop-4;
     }
    }


    function _makeMask()
    {
     var div=document.createElement("DIV");
     with(div.runtimeStyle)
     {
      position="absolute";
      zIndex=999999;
      fontSize="1px";
      left=event.clientX+document.body.scrollLeft-4;
      top=event.clientY+document.body.scrollTop-4;
      width="8px";
      height="8px";
      cursor="wait";
     
      backgroundColor="gray";
      filter="alpha(opacity=10)";
     }
     try
     {
      document.body.insertAdjacentElement("BeforeEnd",div);
      div.onblur=new Function("this.focus()");
      div.focus();
     }
     catch(x){}
     
     if(_divMask)_divMask.removeNode(true);
     _divMask=div;
    }

    function _doPostBackNew(sender,args)
    {
     if(_isPosting)
      return event.returnValue=!(event.cancelBubble=true);

     status="正在更新页面...";
     _doPostBack(sender,args); 
     _isPosting=true;
     _makeMask();
    }

    function _onformsubmit()
    {
     if(_isPosting)
      return event.returnValue=!(event.cancelBubble=true);

     _isPosting=true;
     _makeMask();
    }
    new function _attachForms()
    {
     with(new Enumerator(document.forms))
     for(;!atEnd();moveNext())
     {
      item().attachEvent("onsubmit",_onformsubmit);
      var div=document.createElement("div");
      div.runtimeStyle.width="0px";
      div.runtimeStyle.hight="0px";
      div.runtimeStyle.overflow="hidden";
      div.runtimeStyle.position="absolute";
      item(0).insertAdjacentElement("afterbegin",div);
      div.innerHTML="<INPUT TYPE=Submit name='webformpatchsubmitelement' onclick='return event.returnValue=false' id='webformpatchsubmitelement' value='webformpatchsubmitelement'/>";
     }
    }
    把这个作为 <-script src=js.js-><-/script-> 的形式Render到每个页面中就可以了。|
    如果有PageBase,则在Init的时候用RegisterClientScriptBlock放上去更好。
    如:this.RegisterStartupScript("JS","<script src=\"js.js\" type=\"text/javascript\"></script>");

    我的这个投票基本上处理,能防止一些常见的作弊方法,欢迎大家提出不足之处   
    和漏洞

  • 相关阅读:
    百度地图API
    h5地理位置API
    css3的clip-path属性
    css3的3d属性集合
    模块化之SeaJS(二)
    模块化之SeaJS(一)
    html5制作一个时钟
    闭包论
    UVALive 7066 Intersection(圆环相交面积)
    UVALive 7068 K.Bro Sorting(树状数组求逆序对)
  • 原文地址:https://www.cnblogs.com/nonsuch/p/541558.html
Copyright © 2020-2023  润新知