asp.net如何实现点选验证码
创始人
2024-11-28 04:42:30
0次

先上效果图

asp.net如何实现点选验证码

如果你被这个效果吸引了就请继续看下去。

贴代码前先说点思路:

1.要有一个汉字库,并按字形分类。(我在数据库里是安部首分类的)

2.获取验证码(也就是取几个文字做验证码)

3.根据取出来的文字去找形近字

4.排列验证码文字和形近字

5.绘制图片

6.显示

一、获取字库

我国文化博大精深,辣么多的字从哪儿来?当然我不可能手动加进去,于是我就在网上随便找了一个能查汉字的网站,去抓别人的数据。抓数据的方法请点传送门。传送门里说的只是思路,如果有不明白的请艾特我。我会在下面共享我的字库。

二、获取验证码

这个就比较简单了这里我就直接贴代码了,下面的代码就是随机排序后取4条数据,我这样写是为了图方便。个人觉得先随机生成ID,然后直接根据ID取数据,这样查询速度会比下面这种写法快。(注意我用的数据库是MySql)

  /// 
  /// 获取验证码
  /// 
  public List GetCodeText()
  {
   const string sql = "SELECT * FROM wenzhi ORDER BY RAND() LIMIT 4";
   var dataReader = dbHelper.GetDataReader(sql);
   var list = DataReaderToList(dataReader);
   dataReader.Close();
   return list;
  }

三、根据取出来的文字去找形近字

因为第一步的时候我存部首了,所以这里我直接根据部首取获取当前部首的形近字。

  /// 
  /// 获取答案备选
  /// 
  /// 部首编码
  /// 当前文字ID
  /// 数量
  /// 
  public List GetAnswer(string buShouCode, int id,int number=1)
  {
   string sql = $"SELECT * FROM wenzhi where BuShouCode='{buShouCode}' and ID <> {id} ORDER BY RAND() LIMIT "+ number;
   var dataReader = dbHelper.GetDataReader(sql);
   var list = DataReaderToList(dataReader);
   dataReader.Close();
   return list;
  }

四.排列验证码文字和形近字

下面的代码是先把备选答案和验证码放在一个集合里然后再对集合排序

 public Model.Code GetCode()
  {
   
   var wenzlist = _wenZhiDal.GetCodeText(); //获取验证码
   var listAnsuwr = new List();//实例化备选答案对象
   var answerCode = string.Empty;//答案
   var result = new Model.Code
   {
    Id = Guid.NewGuid().ToString()
   };
   //根据验证码获取备选答案并把添加到答案添加到备选答案集合
   foreach (var item in wenzlist)
   {
    answerCode += item.ID + ",";
    result.AnswerValue += item.Text;
    var answerList = _wenZhiDal.GetAnswer(item.BuShouCode, item.ID);
    listAnsuwr.Add(new Answer { Id = item.ID.ToString(), Img = GetImage(item.Text) });
    listAnsuwr.AddRange(answerList.Select(answer => new Answer { Id = answer.ID.ToString(), Img = GetImage(answer.Text) }));
   }
   //如果答案个数不够就再去取几个
   if (listAnsuwr.Count < 9)
   {
    var ran = new Random();
    var randKey = ran.Next(0, 4);
    var item = wenzlist[randKey];
    var answerList = _wenZhiDal.GetAnswer(item.BuShouCode, item.ID, 9 - listAnsuwr.Count);
    listAnsuwr.AddRange(answerList.Select(answer => new Answer { Id = answer.ID.ToString(), Img = GetImage(answer.Text) }));
   }
   result.CodeImg = GetImage(result.AnswerValue);//获取图片
   result.AnswerValue = answerCode.TrimEnd(',');
   result.Answer = RandomSortList(listAnsuwr);//打乱正确答案与形近字的顺序
   return result;
  }

 这是对集合排序的代码

  /// 
  /// 随机排列集合
  /// 
  /// 
  /// 
  /// 
  private static List RandomSortList(IEnumerable listT)
  {
   var random = new Random();
   var newList = new List();
   foreach (var item in listT)
   {
    newList.Insert(random.Next(newList.Count + 1), item);
   }
   return newList;
  }

五、绘制图片

下面是画图的代码,验证码和备选答案对应两种不同的画法(里面注释写的还算清楚)。不要担心文字旋转x°后人类分不出来,哈哈。代码最后一句我把图片转成了Base64,方便前端调用。

private static string GetImage(string text)
  {
   Image image;
   switch (text.Length)
   {
    case 1:
     image = new Bitmap(50, 40);
     break;
    case 4:
     image = new Bitmap(120, 40);
     break;
    default:
     image = new Bitmap(50, 40);
     break;
   }
   Brush brushText = new SolidBrush(Color.FromArgb(255, 0, 0, 0));
   var graphics = Graphics.FromImage(image);
   graphics.SmoothingMode = SmoothingMode.AntiAlias;
   graphics.Clear(Color.White);
   var font = new Font(new FontFamily("华文彩云"), 20, FontStyle.Regular);
   if (text.Length > 1)//画验证码
   {
    //先来两条直线做干扰 然后再画文字
    graphics.DrawLine(new Pen(brushText, new Random().Next(1, 3)), new Point(new Random().Next(0, 10), new Random().Next(10, 40)), new Point(new Random().Next(100, 120), new Random().Next(10, 30)));
    graphics.DrawLine(new Pen(brushText, new Random().Next(1, 3)), new Point(new Random().Next(20, 50), new Random().Next(0, 10)), new Point(new Random().Next(100, 120), new Random().Next(30, 40)));
    graphics.DrawString(text, font, brushText, 0, 10);

   }
   else//画备选答案
   {
    Point middle = new Point(25, 20);
    graphics.TranslateTransform(middle.X, middle.Y);
    //这里是360°随机旋转 
    graphics.RotateTransform(new Random().Next(0, 360));
    var format = new StringFormat(StringFormatFlags.NoClip)
    {
     Alignment = StringAlignment.Center,
     LineAlignment = StringAlignment.Center
    };
    graphics.DrawString(text, font, brushText, 0, 0, format);

   }
   brushText.Dispose();
   graphics.Dispose();
   return ImageToBase64(image);
  }

六、显示

直接调用GetCode方法就能返回验证码对象

下面是后台代码,应为正确答案是放在AnswerValue里的所以我先把取出来放Session里面,然后把值清空后再通过json返回给浏览器。

  public string GetVerCode()
  {
   var code = new VerificationCode.Code().GetCode();
   Session["VERCODE"] = code.AnswerValue;
   code.AnswerValue = "";
   return JsonConvert.SerializeObject(code);
  }

现在来堆点html代码


     
      
  •       
  •       
  •       
  •                   
           看不清?      
                
  •       
  •       
  •       
  •       
  •       
  •       
  •       
  •       
  •           

    再来点js代码,这里只实现的图片上的效果,还没对数据验证(这里说说验证思路:每个图片对应一个ID,取到选择图片的ID用逗号分隔,然后与Session里的值对比)

    相关内容

    热门资讯

    空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
    空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
    格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
    空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
    格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
    品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
    空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
    空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
    中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
    中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...