找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 2997|回复: 2

【asp.net】asp.net网页验证码生成之“奇葩”方式

[复制链接]

85

主题

175

回帖

3990

积分

用户组: 超级版主

No. 418

UID
418
精华
14
威望
53 点
宅币
1974 个
贡献
1582 次
宅之契约
0 份
在线时间
252 小时
注册时间
2014-8-9
发表于 2015-5-19 17:44:52 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
网上有不少asp.net cs生成验证码的文档
试验了一下,很少能正常工作
于是我想出了一种生成验证码与表单验证分离的架构
好处是因为验证码生成程序分离,可以随时改进验证码生成算法
而不用修改网页代码
坏处是,调用了外部exe增加了服务器的负载
如果大量客户同时登陆,那么服务器和系统将不能正确工作。

先说一下想法:
生成验证码时,用CS调用VB写的EXE文件
VB的EXE在网站服务器目录下生成图片:
pic.bmp和图片答案ans.txt
CS在调用EXE后获取网站目录下图片然后读取答案
在提交表单时将读到的答案与用户填写的字符串进行比对。

关于vb验证码的生成算法,我在这篇帖子中略有叙述
主要算法大家可以参考这里:
【VB】最简单之验证码生成算法
http://www.0xaa55.com/thread-1096-1-1.html
(出处: 技术宅的结界)

这个新的验证码生成程序是在上述程序上改进而成
大致流程:在程序被调用时监测 是否后台运行参数
检测到以后生成验证码到Form的picturebox中
最后将答案输出至文本文件ans.txt,验证码图片用savepicture保
存至当前目录,以供调用。
那么在此贴上这次用的vb程序代码:

  1. VERSION 5.00
  2. Begin VB.Form Form1
  3.    Caption         =   "Form1"
  4.    ClientHeight    =   2940
  5.    ClientLeft      =   60
  6.    ClientTop       =   600
  7.    ClientWidth     =   4680
  8.    LinkTopic       =   "Form1"
  9.    ScaleHeight     =   2940
  10.    ScaleWidth      =   4680
  11.    StartUpPosition =   3  '窗口缺省
  12.    Begin VB.CommandButton Command2
  13.       Caption         =   "OK"
  14.       Enabled         =   0   'False
  15.       Height          =   255
  16.       Left            =   2160
  17.       TabIndex        =   3
  18.       Top             =   480
  19.       Width           =   975
  20.    End
  21.    Begin VB.TextBox Text1
  22.       Height          =   285
  23.       Left            =   -120
  24.       TabIndex        =   2
  25.       Top             =   480
  26.       Width           =   2295
  27.    End
  28.    Begin VB.CommandButton Command1
  29.       Caption         =   "Change"
  30.       Height          =   495
  31.       Left            =   2160
  32.       TabIndex        =   1
  33.       Top             =   0
  34.       Width           =   975
  35.    End
  36.    Begin VB.PictureBox P
  37.       AutoRedraw      =   -1  'True
  38.       BackColor       =   &H00FFFFFF&
  39.       ForeColor       =   &H00000000&
  40.       Height          =   495
  41.       Left            =   0
  42.       ScaleHeight     =   435
  43.       ScaleWidth      =   2115
  44.       TabIndex        =   0
  45.       Top             =   0
  46.       Width           =   2175
  47.    End
  48. End
  49. Attribute VB_Name = "Form1"
  50. Attribute VB_GlobalNameSpace = False
  51. Attribute VB_Creatable = False
  52. Attribute VB_PredeclaredId = True
  53. Attribute VB_Exposed = False
  54. Option Explicit '从这里算真正开始

  55. Dim ans         As Single
  56. Dim bShutdown As Boolean

  57. Private Sub Command1_Click()
  58.     Randomize '初始化随机数生成器
  59.     Command2.Enabled = True '免得不输就pass
  60.     Dim a As Integer, b As Integer, c(3) As String, d As String
  61.     'a放第一个数,b放第二个数,c放操作符,d保存操作符
  62.     Dim i As Integer '计数器变量留着待用
  63.    
  64.     c(1) = "+"
  65.     c(2) = "-"
  66.     c(3) = "*"
  67.    
  68.     a = Int(Rnd * 10 + 1) '第一个随机数
  69.     b = Int(Rnd * 10 + 1) '第二个随机数
  70.    
  71.    
  72.     P.Cls '清屏
  73.     '第一个数
  74.     P.FontName = Screen.Fonts(Int(Rnd * 15) + 1) '字体名
  75.     P.FontSize = Int(Rnd * 16) + 8 '字号
  76.     P.FontBold = CBool(Int(Rnd + 1)) '是否粗体
  77.     P.FontItalic = CBool(Int(Rnd + 1)) '是否斜体
  78.     P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1)) '随机颜色
  79.     P.BackColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
  80.     '定位
  81.     P.CurrentX = Int(Rnd() * 10) + 10
  82.     P.CurrentY = Int(Rnd() * 50) + 1
  83.     P.Print CStr(a) '打印
  84.    
  85.     '操作符
  86.     P.FontName = Screen.Fonts(Int(Rnd * 15) + 1)
  87.     P.FontSize = Int(Rnd * 16) + 8
  88.     P.FontBold = CBool(Int(Rnd + 1))
  89.     P.FontItalic = CBool(Int(Rnd + 1))
  90.     P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
  91.     P.CurrentX = Int(Rnd() * 500) + 500
  92.     P.CurrentY = Int(Rnd() * 50) + 1
  93.     d = c(Int(Rnd * 3) + 1) '随机操作符
  94.     P.Print d
  95.    
  96.     '第二个数字,原理同上,解释略
  97.     P.FontName = Screen.Fonts(Int(Rnd * 15) + 1)
  98.     P.FontSize = Int(Rnd * 16) + 8
  99.     P.FontBold = CBool(Int(Rnd + 1))
  100.     P.FontItalic = CBool(Int(Rnd + 1))
  101.     P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
  102.     P.CurrentX = Int(Rnd() * 1000) + 1000
  103.     P.CurrentY = Int(Rnd() * 50) + 1
  104.     P.Print CStr(b)
  105.    
  106.     '瞎画一些线条
  107.     For i = 1 To 7
  108.         P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
  109.         P.Line (Rnd * P.ScaleWidth, Rnd * P.ScaleWidth)-(Rnd * P.ScaleWidth, Rnd * P.ScaleWidth)
  110.     Next
  111.     '瞎画一些点
  112.     For i = 1 To 100
  113.         P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
  114.         P.PSet (Rnd * P.ScaleWidth, Rnd * P.ScaleWidth)
  115.     Next
  116.    
  117.     '判定运算,计算结果
  118.     Select Case d
  119.     Case "+"
  120.         ans = a + b
  121.     Case "-"
  122.         ans = a - b
  123.     Case "*"
  124.         ans = a * b
  125.     End Select
  126.    
  127.     If bShutdown Then
  128.         Dim fso As New FileSystemObject
  129.         Dim f As TextStream
  130.         Set f = fso.OpenTextFile(App.Path & "\ans.txt",

  131. ForWriting, True)
  132.         f.Write CStr(ans)
  133.         f.Close
  134.         SavePicture P.Image, App.Path & "\pic.bmp"
  135.         End
  136.     End If
  137. End Sub

  138. Private Sub Command2_Click()
  139.     If Val(Text1) = ans And Text1 <> "" Then
  140.         MsgBox "Pass!", 48
  141.     Else
  142.         Call Command1_Click
  143.         Text1 = ""
  144.     End If
  145. End Sub

  146. Private Sub Form_Load()
  147.     If InStr(LCase(Command$), "-backstage") <> 0 Then
  148.         Me.Visible = False
  149.         bShutdown = True
  150.     End If
  151.     Call Command1_Click
  152. End Sub

复制代码


以下是网页cs实现的细节:
在网页中验证码图片用ImageButton存贮
使用ImageButton的ImageUrl属性给图片
那么使用Click事件则可以进行图片的改换
后来发现ImageButton的图片不能刷新
使用Response.AddHeader("Refresh", "0"); 刷新页面
图片即可正常显示:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.UI;
  6. using System.Web.UI.WebControls;
  7. //操作数据库需要的声明
  8. using System.Data;
  9. using System.Configuration;
  10. using System.Collections;
  11. using System.Data.SqlClient;
  12. //调用外部EXE需要的声明
  13. using System.Diagnostics;
  14. using System.IO;

  15. public partial class Default2 : System.Web.UI.Page
  16. {
  17.     protected void Page_Load(object sender, EventArgs e)
  18.     {
  19.         ImageButton1.ImageUrl = "pic.bmp";//在初始化页面时引入图片     
  20.     }
  21.     protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
  22.     {
  23.         GenerateACodeMap();//切换图片时重新加载图片
  24.         Response.AddHeader("Refresh", "0"); //刷新页面
  25.     }
  26.     protected void Button1_Click(object sender, EventArgs e)
  27.     {
  28.         string conStr = ConfigurationManager.ConnectionStrings["ConnectionStringMain"].ToString();
  29.         SqlConnection myConn = new SqlConnection(conStr);
  30.         myConn.Open();

  31.         string queueStr = "SELECT * FROM AdminsTable WHERE Username = '" + TextBox1.Text + "' AND Password = '" + TextBox2.Text + "'";
  32.         SqlCommand myCmd = new SqlCommand(queueStr, myConn);
  33.         SqlDataReader myRdr = myCmd.ExecuteReader();
  34.         //以上为连接数据库并查询
  35.         string currentpath = System.AppDomain.CurrentDomain.BaseDirectory;//获取当前地址
  36.         StreamReader sr = new StreamReader(currentpath + "ans.txt");
  37.         String vcodeStr = sr.ReadLine();//获取服务器上存储的答案文件
  38.         sr.Close();//关闭对文件的访问

  39.         if (TextBox3.Text == vcodeStr.Replace("\n", ""))//判断验证码
  40.         {
  41.             if (myRdr.Read())//如果读到正确用户名与密码
  42.             {
  43.                 Response.Write("<script>window.alert('hello!');</script>");//登陆成功
  44.             }
  45.             else
  46.             {
  47.                 Response.Write("<script>window.alert('Bad Username Or Password!');</script>");//用户名密码错误
  48.                 TextBox1.Text = ""; TextBox2.Text = ""; TextBox3.Text = "";
  49.             }
  50.         }
  51.         else
  52.         {
  53.             Response.Write("<script>window.alert('Bad Verifying Code!');</script>");//验证码错误
  54.         }
  55.         GenerateACodeMap();//刷新验证码
  56.     }
  57.     void GenerateACodeMap()//生成验证码
  58.     {
  59.         System.Diagnostics.ProcessStartInfo p = null;
  60.         System.Diagnostics.Process Proc;

  61.         string currentpath = System.AppDomain.CurrentDomain.BaseDirectory;
  62.         p = new ProcessStartInfo("vcg.exe", "-backstage");//调用EXE给参“后台”
  63.         p.WorkingDirectory = currentpath;
  64.         p.WindowStyle = ProcessWindowStyle.Normal;
  65.         
  66.         Proc = System.Diagnostics.Process.Start(p);

  67.         while (Proc.HasExited == false)//等待直到进程退出
  68.         {
  69.             if (Proc.HasExited == true)
  70.             {
  71.                 ImageButton1.ImageUrl = "pic.bmp";//获取图片
  72.             }
  73.             else
  74.             {
  75.                 ImageButton1.ImageUrl = "default.bmp";//获取不到图片 显示缺省图片
  76.             }
  77.         }
  78.     }
  79. }
复制代码



具体实现:
用vs创建一只asp.net网站,使用cs语言。
建立一个如图页面:
aa.JPG

将上述cs代码写入

将vb生成的exe命名为VCG放置在网站根目录下。
cc.JPG


这样整个系统便完成了。
In the beginning I was not the best.
And the world was also not the best.
But I still know that I am who I am.
Because I think that it is good.
I have been working hard.
I have been keeping growth with the world.
And it was so.
回复

使用道具 举报

85

主题

175

回帖

3990

积分

用户组: 超级版主

No. 418

UID
418
精华
14
威望
53 点
宅币
1974 个
贡献
1582 次
宅之契约
0 份
在线时间
252 小时
注册时间
2014-8-9
 楼主| 发表于 2015-5-19 17:49:28 | 显示全部楼层
哦 天哪 我的代码你肿么了!{:soso_e126:}
In the beginning I was not the best.
And the world was also not the best.
But I still know that I am who I am.
Because I think that it is good.
I have been working hard.
I have been keeping growth with the world.
And it was so.
回复 赞! 靠!

使用道具 举报

1111

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24237 个
贡献
46222 次
宅之契约
0 份
在线时间
2297 小时
注册时间
2014-1-26
发表于 2015-5-19 22:29:21 | 显示全部楼层
cyycoish 发表于 2015-5-19 17:49
哦 天哪 我的代码你肿么了!

要学会不断编辑调整帖子……
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-20 18:26 , Processed in 0.043878 second(s), 34 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表