- UID
- 418
- 精华
- 积分
- 3994
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
网上有不少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程序代码:
- VERSION 5.00
- Begin VB.Form Form1
- Caption = "Form1"
- ClientHeight = 2940
- ClientLeft = 60
- ClientTop = 600
- ClientWidth = 4680
- LinkTopic = "Form1"
- ScaleHeight = 2940
- ScaleWidth = 4680
- StartUpPosition = 3 '窗口缺省
- Begin VB.CommandButton Command2
- Caption = "OK"
- Enabled = 0 'False
- Height = 255
- Left = 2160
- TabIndex = 3
- Top = 480
- Width = 975
- End
- Begin VB.TextBox Text1
- Height = 285
- Left = -120
- TabIndex = 2
- Top = 480
- Width = 2295
- End
- Begin VB.CommandButton Command1
- Caption = "Change"
- Height = 495
- Left = 2160
- TabIndex = 1
- Top = 0
- Width = 975
- End
- Begin VB.PictureBox P
- AutoRedraw = -1 'True
- BackColor = &H00FFFFFF&
- ForeColor = &H00000000&
- Height = 495
- Left = 0
- ScaleHeight = 435
- ScaleWidth = 2115
- TabIndex = 0
- Top = 0
- Width = 2175
- End
- End
- Attribute VB_Name = "Form1"
- Attribute VB_GlobalNameSpace = False
- Attribute VB_Creatable = False
- Attribute VB_PredeclaredId = True
- Attribute VB_Exposed = False
- Option Explicit '从这里算真正开始
- Dim ans As Single
- Dim bShutdown As Boolean
- Private Sub Command1_Click()
- Randomize '初始化随机数生成器
- Command2.Enabled = True '免得不输就pass
- Dim a As Integer, b As Integer, c(3) As String, d As String
- 'a放第一个数,b放第二个数,c放操作符,d保存操作符
- Dim i As Integer '计数器变量留着待用
-
- c(1) = "+"
- c(2) = "-"
- c(3) = "*"
-
- a = Int(Rnd * 10 + 1) '第一个随机数
- b = Int(Rnd * 10 + 1) '第二个随机数
-
-
- P.Cls '清屏
- '第一个数
- P.FontName = Screen.Fonts(Int(Rnd * 15) + 1) '字体名
- P.FontSize = Int(Rnd * 16) + 8 '字号
- P.FontBold = CBool(Int(Rnd + 1)) '是否粗体
- P.FontItalic = CBool(Int(Rnd + 1)) '是否斜体
- P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1)) '随机颜色
- P.BackColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
- '定位
- P.CurrentX = Int(Rnd() * 10) + 10
- P.CurrentY = Int(Rnd() * 50) + 1
- P.Print CStr(a) '打印
-
- '操作符
- P.FontName = Screen.Fonts(Int(Rnd * 15) + 1)
- P.FontSize = Int(Rnd * 16) + 8
- P.FontBold = CBool(Int(Rnd + 1))
- P.FontItalic = CBool(Int(Rnd + 1))
- P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
- P.CurrentX = Int(Rnd() * 500) + 500
- P.CurrentY = Int(Rnd() * 50) + 1
- d = c(Int(Rnd * 3) + 1) '随机操作符
- P.Print d
-
- '第二个数字,原理同上,解释略
- P.FontName = Screen.Fonts(Int(Rnd * 15) + 1)
- P.FontSize = Int(Rnd * 16) + 8
- P.FontBold = CBool(Int(Rnd + 1))
- P.FontItalic = CBool(Int(Rnd + 1))
- P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
- P.CurrentX = Int(Rnd() * 1000) + 1000
- P.CurrentY = Int(Rnd() * 50) + 1
- P.Print CStr(b)
-
- '瞎画一些线条
- For i = 1 To 7
- P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
- P.Line (Rnd * P.ScaleWidth, Rnd * P.ScaleWidth)-(Rnd * P.ScaleWidth, Rnd * P.ScaleWidth)
- Next
- '瞎画一些点
- For i = 1 To 100
- P.ForeColor = RGB(Int(Rnd * 254 + 1), Int(Rnd * 254 + 1), Int(Rnd * 254 + 1))
- P.PSet (Rnd * P.ScaleWidth, Rnd * P.ScaleWidth)
- Next
-
- '判定运算,计算结果
- Select Case d
- Case "+"
- ans = a + b
- Case "-"
- ans = a - b
- Case "*"
- ans = a * b
- End Select
-
- If bShutdown Then
- Dim fso As New FileSystemObject
- Dim f As TextStream
- Set f = fso.OpenTextFile(App.Path & "\ans.txt",
- ForWriting, True)
- f.Write CStr(ans)
- f.Close
- SavePicture P.Image, App.Path & "\pic.bmp"
- End
- End If
- End Sub
- Private Sub Command2_Click()
- If Val(Text1) = ans And Text1 <> "" Then
- MsgBox "Pass!", 48
- Else
- Call Command1_Click
- Text1 = ""
- End If
- End Sub
- Private Sub Form_Load()
- If InStr(LCase(Command$), "-backstage") <> 0 Then
- Me.Visible = False
- bShutdown = True
- End If
- Call Command1_Click
- End Sub
复制代码
以下是网页cs实现的细节:
在网页中验证码图片用ImageButton存贮
使用ImageButton的ImageUrl属性给图片
那么使用Click事件则可以进行图片的改换
后来发现ImageButton的图片不能刷新
使用Response.AddHeader("Refresh", "0"); 刷新页面
图片即可正常显示:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- //操作数据库需要的声明
- using System.Data;
- using System.Configuration;
- using System.Collections;
- using System.Data.SqlClient;
- //调用外部EXE需要的声明
- using System.Diagnostics;
- using System.IO;
- public partial class Default2 : System.Web.UI.Page
- {
- protected void Page_Load(object sender, EventArgs e)
- {
- ImageButton1.ImageUrl = "pic.bmp";//在初始化页面时引入图片
- }
- protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
- {
- GenerateACodeMap();//切换图片时重新加载图片
- Response.AddHeader("Refresh", "0"); //刷新页面
- }
- protected void Button1_Click(object sender, EventArgs e)
- {
- string conStr = ConfigurationManager.ConnectionStrings["ConnectionStringMain"].ToString();
- SqlConnection myConn = new SqlConnection(conStr);
- myConn.Open();
- string queueStr = "SELECT * FROM AdminsTable WHERE Username = '" + TextBox1.Text + "' AND Password = '" + TextBox2.Text + "'";
- SqlCommand myCmd = new SqlCommand(queueStr, myConn);
- SqlDataReader myRdr = myCmd.ExecuteReader();
- //以上为连接数据库并查询
- string currentpath = System.AppDomain.CurrentDomain.BaseDirectory;//获取当前地址
- StreamReader sr = new StreamReader(currentpath + "ans.txt");
- String vcodeStr = sr.ReadLine();//获取服务器上存储的答案文件
- sr.Close();//关闭对文件的访问
- if (TextBox3.Text == vcodeStr.Replace("\n", ""))//判断验证码
- {
- if (myRdr.Read())//如果读到正确用户名与密码
- {
- Response.Write("<script>window.alert('hello!');</script>");//登陆成功
- }
- else
- {
- Response.Write("<script>window.alert('Bad Username Or Password!');</script>");//用户名密码错误
- TextBox1.Text = ""; TextBox2.Text = ""; TextBox3.Text = "";
- }
- }
- else
- {
- Response.Write("<script>window.alert('Bad Verifying Code!');</script>");//验证码错误
- }
- GenerateACodeMap();//刷新验证码
- }
- void GenerateACodeMap()//生成验证码
- {
- System.Diagnostics.ProcessStartInfo p = null;
- System.Diagnostics.Process Proc;
- string currentpath = System.AppDomain.CurrentDomain.BaseDirectory;
- p = new ProcessStartInfo("vcg.exe", "-backstage");//调用EXE给参“后台”
- p.WorkingDirectory = currentpath;
- p.WindowStyle = ProcessWindowStyle.Normal;
-
- Proc = System.Diagnostics.Process.Start(p);
- while (Proc.HasExited == false)//等待直到进程退出
- {
- if (Proc.HasExited == true)
- {
- ImageButton1.ImageUrl = "pic.bmp";//获取图片
- }
- else
- {
- ImageButton1.ImageUrl = "default.bmp";//获取不到图片 显示缺省图片
- }
- }
- }
- }
复制代码
具体实现:
用vs创建一只asp.net网站,使用cs语言。
建立一个如图页面:
将上述cs代码写入
将vb生成的exe命名为VCG放置在网站根目录下。
这样整个系统便完成了。
|
|