【转】开发基于ASP.NET WebService的图片验证码服务

2023-11-16

原文地址:http://www.webjx.com/htmldata/2006-01-21/1137824356.html

最近,工作中接到一项任务,开发一个页面验证码功能,查阅了一些网上的资料,并结合以前的绘图方面的知识,实现了如下的解决方案。生成的验证码效果如图:

开发基于ASP.NET WebService的图片验证码服务

  要解决的问题:

  1. 如何随机生成图片

    生成System.Drawing.Bitmap对象,使用System.Drawing.Graphics向位图对象中绘图。

  2. 如何在WebService的方法中通过参数传递图片数据

    将Bitmap对象输出成字节流,WebMothod使用字节数组返回该字节流。

  实例:

  1. 用VS.NET 2003创建一个ASP.NET Webservice工程,默认的Service名为MyService,为MyService添加一个名为GenerateVerifyImage的WebMethod。该方法的代码如下:

  /// <summary>
  /// 生成图片验证码
  /// </summary>
  /// <param name="nLen">验证码的长度</param>
  /// <param name="strKey">输出参数,验证码的内容</param>
  /// <returns>图片字节流</returns>
  [WebMethod]
  public byte[] GenerateVerifyImage(int nLen,ref string strKey)
  {
   int nBmpWidth = 13*nLen+5;
   int nBmpHeight = 25;
   System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(nBmpWidth,nBmpHeight);

   // 1. 生成随机背景颜色
   int nRed,nGreen,nBlue;  // 背景的三元色
   System.Random rd = new Random((int)System.DateTime.Now.Ticks);
   nRed = rd.Next(255)%128+128;
   nGreen = rd.Next(255)%128+128;
   nBlue = rd.Next(255)%128+128;

   // 2. 填充位图背景
   System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(bmp);
   graph.FillRectangle(new SolidBrush(System.Drawing.Color.FromArgb(nRed,nGreen,nBlue))
    ,0
    ,0
    ,nBmpWidth
    ,nBmpHeight);


   // 3. 绘制干扰线条,采用比背景略深一些的颜色
   int nLines = 3;
   System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.FromArgb(nRed-17,nGreen-17,nBlue-17),2);
   for(int a =0;a< nLines;a++)
   {
    int x1 = rd.Next() % nBmpWidth;
    int y1 = rd.Next() % nBmpHeight;
    int x2 = rd.Next() % nBmpWidth;
    int y2 = rd.Next() % nBmpHeight;
    graph.DrawLine(pen,x1,y1,x2,y2);
   }

   // 采用的字符集,可以随即拓展,并可以控制字符出现的几率
   string strCode = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";  

   // 4. 循环取得字符,并绘制
   string strResult = "";
   for(int i=0;i<nLen;i++)
   {
    int x = (i*13 + rd.Next(3));
    int y = rd.Next(4) + 1;

    // 确定字体
    System.Drawing.Font font = new System.Drawing.Font("Courier New",
     12 + rd.Next()%4,
     System.Drawing.FontStyle.Bold);
    char c = strCode[rd.Next(strCode.Length)];  // 随机获取字符
    strResult += c.ToString();

    // 绘制字符
    graph.DrawString(c.ToString(),
     font,
     new SolidBrush(System.Drawing.Color.FromArgb(nRed-60+y*3,nGreen-60+y*3,nBlue-40+y*3)),
     x,
     y);
   }

   // 5. 输出字节流
   System.IO.MemoryStream bstream = new System.IO.MemoryStream();
   bmp.Save(bstream,System.Drawing.Imaging.ImageFormat.Jpeg);
   bmp.Dispose();
   graph.Dispose();

   strKey = strResult;
   byte[] byteReturn = bstream.ToArray();
   bstream.Close();

   return byteReturn;
  }

  2. 测试WebMethod,添加一个WebForm,引用上述WebService,引用名为imagesvr。在Page_Load中添加代码:

   ...
   imagesvr.MyService imgsvr = new imagesvr.MyService();
   string strKey = "";
   byte[] data = imgsvr.GenerateVerifyImage(5,ref strKey);
   Response.OutputStream.Write(data,0,data.Length);
   ...

  3. 运行。每次refresh这个WebForm时,就会显示一个新生成的图片验证码,而函数的输出参数strKey保存的就是这个验证码的实际内容,可以保存在Session中,作为验证使用。

  上次开发出图片验证码之后,根据一些朋友的建议,本着验证码易识别(针对人),不易破解,美观的原则,改进了验证码生成的算法,采用图像滤镜的方法,对图片验证码进行反破解干扰,结果图片示例如下:

开发基于ASP.NET WebService的图片验证码服务

  滤镜效果主要采用波形(wave)算法,通过对X轴Y轴的正弦波形处理,产生叠加效果。算法主要描述如下:

  private const double PI = 3.1415926535897932384626433832795;
  private const double PI2 = 6.283185307179586476925286766559;

  /// <summary>
  /// 正弦曲线Wave扭曲图片
  /// </summary>
  /// <param name="srcBmp"></param>
  /// <param name="bXDir"></param>
  /// <param name="nMultValue">波形的幅度倍数</param>
  /// <param name="dPhase">波形的起始相位,取值区间[0-2*PI)</param>
  /// <returns></returns>
  public System.Drawing.Bitmap TwistImage(Bitmap srcBmp,bool bXDir,double dMultValue,double dPhase)
  {
   System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width,srcBmp.Height);

   // 将位图背景填充为白色
   System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(destBmp);
   graph.FillRectangle(new SolidBrush(System.Drawing.Color.White),0,0,destBmp.Width,destBmp.Height);
   graph.Dispose();
  
   double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width;

   for(int i=0;i<destBmp.Width;i++)
   {
    for(int j=0;j<destBmp.Height;j++)
    {
     double dx = 0;
     dx = bXDir ? (PI2*(double)j)/dBaseAxisLen : (PI2*(double)i)/dBaseAxisLen;
     dx += dPhase;
     double dy = Math.Sin(dx);

     // 取得当前点的颜色
     int nOldX = 0,nOldY = 0;
     nOldX = bXDir ? i + (int)(dy*dMultValue) : i;
     nOldY = bXDir ? j : j + (int)(dy*dMultValue);

     System.Drawing.Color color = srcBmp.GetPixel(i,j);
     if(nOldX >= 0 && nOldX < destBmp.Width
      && nOldY >=0 && nOldY < destBmp.Height)
     {
      destBmp.SetPixel(nOldX,nOldY,color);
     }
    }
   }

   return destBmp;
  }

  开头的示例图片,是两次波形效果的叠加,两次效果分别针对X轴方向和Y轴方向,如果取消对边缘背景色的填充,可以看到算法对图形的影响,如下图:

开发基于ASP.NET WebService的图片验证码服务

  这样产生的验证码,看起来很像Google站点上的验证码吧,当然,如果你有兴趣,还可以添加其他的滤镜效果,如拉伸,旋转,马赛克等。但是注意一点,网站验证码不是越复杂越好,要在速度和安全上找到一个平衡点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【转】开发基于ASP.NET WebService的图片验证码服务 的相关文章

  • 仅在页面加载时执行 Javascript,而不是回发 (SharePoint)

    我正在尝试在 SharePoint 网站上的自定义页面上加载页面时执行一些 JavaScript 它使用当前用户填充人员选择器 问题是代码也在回发时执行 这是我不希望的 因为它会重置人员选择器的任何更改 我尝试过使用if IsPostBac
  • 在 Asp.Net MVC 视图中使用 dropdownlistfor 和 foreach 吗?

    我有一个带有 foreach 循环的视图 用于模型的列表属性 现在 我希望能够让用户使用下拉列表设置列表中每个项目的值 但我不知道该怎么做 当它不在 foreach 循环中时 我使用过类似的东西 Html DropDownListFor m
  • 如何将 .ashx 处理程序与 asp:Image 对象一起使用?

    我有一个 ashx 处理程序 using System using System Web public class Thumbnail IHttpHandler public void ProcessRequest HttpContext
  • 从文件 C 中的单行读取多个变量类型

    好吧 我一整天都在做这个 但我一辈子都无法把它记下来 也许你们可以帮忙 我有一个文件 内容如下 1301 105515018 水手长 迈克尔 R ABC 123 R01 1301 103993269 卡斯蒂利亚 小迈克尔 ABC 123 R
  • C 中带有指针的 For 循环

    我不明白指针在其中的作用for loop 什么是 p在下面的循环中做什么 char str 128 Some Text char p for p str p what does this mean p Code 其余的我都明白 但为什么不明
  • sitecore 站点内嵌套虚拟目录或应用程序是否可能

    我想将 ASP NET Web 应用程序嵌套在 sitecore 站点中 如下所示
  • ASP.NET MVC 多线程

    我想在我的 asp net mvc 应用程序中实现这样的逻辑 user clicks a button gt server executes some time consuming logic in 15 threads i get dat
  • 将 UserControl 转换为特定类型的用户控件

    有没有办法将用户控件转换为特定的用户控件 以便我可以访问它的公共属性 基本上 我正在遍历占位符的控件集合 并尝试访问用户控件的公共属性 foreach UserControl uc in plhMediaBuys Controls uc P
  • python中的StringIO实际用途是什么?

    StringIO到底是用来做什么的 我一直在互联网上寻找一些例子 然而 几乎所有的例子都非常抽象 他们只是展示 如何 使用它 但它们都没有表明 为什么 和 在什么情况下 应该 将使用它 附注不要与 stackoverflow 上的这个问题混
  • ASP.NET WebApi - 一个控制器中的多个 GET 操作

    I have Users控制器和基本 REST 模式工作得很好 不过我需要一种额外的模式users id usergroups这将返回该用户的所有用户组 实现这一点的最佳方法是什么 因为我想我将需要在更多控制器上使用类似的路由 仅使用默认值
  • 导出到 CSV 时 Gridview 出现空行

    这个问题是由进一步讨论引发的这个问题 https stackoverflow com questions 6674555 export gridview data into csv file 6674589 noredirect 1 com
  • realloc():重新分配为 char * 上的 strcat 腾出空间时下一个大小无效 [重复]

    这个问题在这里已经有答案了 我在以下代码中收到无效内存错误 printf s n FINE 5 printf s LENGTH IS d n FINE 6 strlen buffer char realloc buffer strlen b
  • 从呈现的控件 ID 中删除 ctl00$ContentBody$

    我对现有的应用程序进行了一些更改 该应用程序以前只是简单的 HTML 和 Javascript 为了添加服务器端功能 我选择了 ASP NET 并利用了母版页概念 不幸的是 在一个巨大的 Web 表单上 控件 ID 全部被 ctl00 Co
  • 如何实现 Vec 的修剪?

    Rust 提供了字符串的修剪方法 str trim http doc rust lang org stable std primitive str html method trim删除前导和尾随空格 我想要一个对字节串执行相同操作的方法 应
  • ASP.NET 更改模板字段中 Gridview 单元格中的文本和颜色

    我在 ASP net 中有 Gridview 显示数据 根据数据 它会根据单元格的值更改颜色和文本 当列不是模板字段时 这可以正常工作 WORKS WHEN IS NOT A TEMPLATE FIELD if e Row RowType
  • ASP.NET MVC ActionFilterAttribute 在模型绑定之前注入值

    我想创建一个自定义操作过滤器属性 该属性在模型绑定期间可访问的 HttpContext 项中添加一个值 我尝试将其添加到 OnActionExecuting 中 但似乎模型绑定是在过滤器之前执行的 你知道我该怎么做吗 也许模型绑定器中有一个
  • 序列包含多个元素

    我在通过 Linq 获取 RhsTruck 类型的列表并显示它们时遇到一些问题 RhsTruck 只有属性 品牌 型号 序列号 等 RhsCustomer 具有 CustomerName CustomerAddress 等属性 我不断收到错
  • Asp.net错误无法加载文件或程序集[重复]

    这个问题在这里已经有答案了 可能的重复 计算机崩溃后 我的 Visual Studio 2010 将无法加载程序集 https stackoverflow com questions 4975455 after a computer cra
  • ClickOnce 应用程序错误:部署和应用程序没有匹配的安全区域

    我在 IE 中使用 FireFox 和 Chrome 的 ClickOnce 应用程序时遇到问题 它工作正常 异常的详细信息是 PLATFORM VERSION INFO Windows 6 1 7600 0 Win32NT Common
  • 动态添加 ASP.Net 控件

    我有一个存储过程 它根据数据库中存储的记录数返回多行 现在我想有一种方法来创建 div 带有包含该行值的控件的标记 如果从数据库返回 10 行 则 10 div 必须创建标签 我有下面的代码来从数据库中获取结果 但我不知道如何从这里继续 S

随机推荐

  • 表单页面美化(html、css)

    表单页面美化 html css 效果图片 实现代码 html部分就是平常的输入框 div class mainfont h1 在线预约 h1 div div class form div
  • OSW

    OSWatcher 工具 下载文档 Metalink Doc ID 301137 1 Oswatcher 主要用于监控主机资源 如CPU 内存 网络以及私有网络等 其中私有网络需要单独配置 需要说明的执行OSWatcher用户需要常见OS
  • 密码学概述

    一 密码学的起源与发展 密码学英文名称为Cryptography 密码学最为一门学科 是最近几十年开始迅速被人们重视和发展起来的 密码学往往与信息安全四个字精密的联系着 最早的密码学的 始祖 可以说是早在公元前几百年就已经出现了 当然 当时
  • 使用JDWP远程debug

    JDWP JDWP是Java Debug Wire Protocol 的缩写 它 定义了调试器 debugger 和被调试的Java虚拟机 target vm 之间的通信协议 SpringBoot debug 1 springboot框架搭
  • detr复现

    https github com IDEA Research detrex 先跑通 相关原理和代码后续解读
  • springboot不同版本整合elasticsearch

    使用springboot整合elasticsearch时候 需要注意版本的对应关系 不然问题会非常多 对应关系如下 springboot2 1整合 elasticsearch的两个方式 通过spring data es springboot
  • Typora软件下载与安装及使用技巧(保姆式教学)

    Typora的下载安装 当前 Typora 是一款支持实时预览的 Markdown 文本编辑器 深受广大程序员的喜爱 简洁明了 方便操作 下面来讲一下它的详细下载安装过程叭 下载安装过程 Typora的下载官网 https typoraio
  • 微信小程序云开发上传图片无法预览显示

    这是图片无法预览显示的情况 而且文件格式显示也不显示为图片格式 不要忘记要在起完名字后加上你希望的图片格式后缀名 加完之后就可以正常显示了
  • Linux链接脚本lds概述

    一 概论 ld 用来把一定量的目标文件跟档案文件链接在一起 并重新定位它们的数据 链接符号引用 一般编译一个程序时 最后一步就是运行ld进行链接 每一个链接过程都由链接脚本 linker script 一般以lds作为文件的后缀名 控制 链
  • 说说你对Object.defineProperty()的理解

    代码在最后 定义 Object defineProperty 方法会直接在一个对象上定义一个新属性 或者修改一个对象的现有属性 并返回此对象 Object defineProperty obj prop descriptor obj 要定义
  • Python糖尿病人预测是否患癌症

    Python糖尿病人预测是否患癌症 统计回归分析的任务 就在于根据x1 x2 x3 xp线性回归和Y的观察值 去估计函数f 寻求变量之间近似的函数关系 我们常用的是 假定f函数的数学形式已知 其中若干个参数未知的观察值去估计未知的参数值 这
  • 网马解密初级篇

    一 网页挂马的概念 网页挂马是指 在获取网站或者网站服务器的部分或者全部权限后 在网页文件中插入一段恶意代码 这些恶意代码主要是一些包括IE等漏洞利用代码 用户访问被挂马的页面时 如果系统没有更新恶意代码中利用的漏洞补丁 则会执行恶意代码程
  • nodejs egg框架统一错误信息返回封装

    use strict app middleware error handler js module exports gt return async function errorHandler ctx next try await next
  • ubuntu内网安装软件

    在生产环境中很少有连接外网的服务器 这里以ansible内网安装为例来介绍 1 安装ansible 有外网 1 ansible的安装包存在于ansible的PPA中 如果要下载PPA 个人软件包存档 就必须要使用apt add reposi
  • C++三角函数计算及弧度制角度制转换

    c 中所有三角函数计算里都是弧度制 用acos算出的弧度t转化为角度的时候 需要t 180 Pi 相对应的 角度换弧度需要t Pi 180 反三角函数 double acos double asin double atan
  • linux怎么看sdb1里面的文件,linux – 什么是sda,sdb,dm-0,dm-1的文档

    如果我运行iostat 我得到了 sda0 sda1 我知道那些是 硬盘 那么有dm 0 dm 1 我想查看文档 我的mount命令也显示了这个 dev mapper VolGroup lv root ext4 usrjquota quot
  • 数据库系统概论(章节重点)

    单词错误 有些地方说的也不是很严谨 大家稍微参考一下即可 祝大家期末顺利 数据库考试重点 题型 30分客观题 20选择10填空或反过来 覆盖面大 关系代数 70分主观题 简答 4 6个理论部分例如简述数据库设计步骤 编程 20 30分 设计
  • input的onchange事件实际触发条件与解决方法

    input中onchange事件已经属于元老级别了 并且现在同onclick一样使用频率很高 然而onchange的机制实际上有很多童鞋并不清楚 我们通过实例来分析这个事件的特征 触发onchange 首先页面有一个input标签 并且已绑
  • python 多线程 线程池的四种实现方式

    python 线程池的四种实现方式 线程简述 一个程序运行起来后 一定有一个执行代码的东西 这个东西就是线程 一般计算 CPU 密集型任务适合多进程 IO密集型任务适合多线程 一个进程可拥有多个并行的 concurrent 线程 当中每一个
  • 【转】开发基于ASP.NET WebService的图片验证码服务

    原文地址 http www webjx com htmldata 2006 01 21 1137824356 html 最近 工作中接到一项任务 开发一个页面验证码功能 查阅了一些网上的资料 并结合以前的绘图方面的知识 实现了如下的解决方案