驗證碼一直是避免網頁機器人透過程式的方式自動登入、輸入的一種常見方式,本篇參考Dotjum的【Captcha 安全碼[ASP.NET] 產生驗證圖片字】,修改成VB.NET的版本而成。並且配合Login登入驗證控制項來處理,有需要的請參考看看。
緣起:
驗證碼一直是避免網頁機器人透過程式的方式自動登入、輸入的一種常見方式,本篇參考Dotjum的【Captcha 安全碼[ASP.NET] 產生驗證圖片字】,修改成VB.NET的版本而成。並且配合Login登入驗證控制項來處理,有需要的請參考看看。
準備產生驗證碼程式:
- 首先,我們先新增一個產生驗證圖形、並且將驗證的碼存到Session等候驗證。先新增一個ASP.NET檔案,檔名就稱為【CheckImageCode.aspx】
- 在aspx裡面不用做任何的安排,直接編寫後置程式碼【CheckImageCode.aspx.vb】
- 新增一個亂數產生驗證碼的Private Function,並且將亂數產生的驗證碼存放在Session裡面,相關程式碼如下:
其中產生驗證碼,透過取得0與A的Ascii Code再加上亂數取得的數字分別數字mod 10、文字mod 26,產生亂碼Private Function GenerateCheckCode() As String Dim number As Integer Dim code As Char Dim checkCode As String = String.Empty Dim random As System.Random = New Random() '要製造出幾個驗證碼 For i As Integer = 0 To 3 'number = random.[Next]() number = random.Next '亂數決定哪一個是數字或字母 If number Mod 2 = 0 Then code = CChar(ChrW(Asc("0") + (number Mod 10))) Else code = CChar(ChrW(Asc("A") + (number Mod 26))) End If checkCode += code.ToString() Next '寫入Session Session("CheckCode") = checkCode Return checkCode End Function
- 新增一個畫出驗證碼圖形的Private Sub,而由於需要產生圖形,先Import 【System.Drawing】,接著撰寫畫出驗證碼的Function,並且亂數產生雜點,避免網路機器人透過圖形辨識來識別出驗證碼
Private Sub CreateCheckCodeImage(ByVal checkCode As String) If checkCode Is Nothing OrElse checkCode.Trim() = [String].Empty Then Return End If 'System.Drawing.Bitmap image = new System.Drawing.Bitmap((int)Math.Ceiling((checkCode.Length * 12.5)), 22); 'System.Drawing.Bitmap image = new System.Drawing.Bitmap((int)Math.Ceiling((checkCode.Length * 20)), 40); Dim image As New System.Drawing.Bitmap(100, 30) Dim g As Graphics = Graphics.FromImage(image) Try '生成隨機生成器 Dim random As New Random() '清空圖片背景色 g.Clear(Color.White) '畫圖片的背景噪音線 For i As Integer = 0 To 24 Dim x1 As Integer = random.[Next](image.Width) Dim x2 As Integer = random.[Next](image.Width) Dim y1 As Integer = random.[Next](image.Height) Dim y2 As Integer = random.[Next](image.Height) g.DrawLine(New Pen(Color.Silver), x1, y1, x2, y2) Next Dim font As Font = New System.Drawing.Font("Arial", 22, (System.Drawing.FontStyle.Bold Or System.Drawing.FontStyle.Italic)) Dim brush As 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); g.DrawString(checkCode, font, brush, 2, 2) '畫圖片的前景噪音點 For i As Integer = 0 To 499 Dim x As Integer = random.[Next](image.Width) Dim y As Integer = random.[Next](image.Height) image.SetPixel(x, y, Color.FromArgb(random.Next)) Next '畫圖片的邊框線 g.DrawRectangle(New Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1) Dim ms As 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() End Try End Sub
- 最後,在【Page Load】事件中呼叫此兩個Function,產生驗證碼、Cookie、圖形。
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load CreateCheckCodeImage(GenerateCheckCode()) End Sub
安排Login相關事宜
這個部分,要麻煩讀者您參考小喵的這篇【ASP.NET的驗證與授權機制(動態錄影說明)】,準備好登入的相關設定。
準備Login的資料夾與畫面
小喵新增一個目錄【Account】,把登入(Login.aspx)、產生驗證碼(CheckImageCode.aspx)的aspx放在此目錄,還需要設定此目錄【允許所有使用者瀏覽】,這很重要,如果此目錄的設定是【拒絕匿名使用者】,那麼【產生驗證碼】的aspx將因為無權限而無法產生。可以在Account這資料夾裡面,設定Web.Config如下,就可以讓此資料夾允許任何使用者。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</configuration>
接著來安排Login.aspx的內容,首先準備畫面如下:
<asp:Image ID="imgChkCode" ImageUrl="~/Account/CheckImageCode.aspx" runat="server" />
<asp:Button ID="btnReGenCode" runat="server" Text="重產驗證碼" />
<br />
<asp:TextBox ID="txtChkCode" runat="server"></asp:TextBox>
<asp:Login ID="Login1" runat="server">
</asp:Login>
<asp:Label ID="lblMsg" runat="server" Text=""></asp:Label>
我們放置一個Image控制項,而source指向產生驗證碼的CheckImageCode.aspx,這樣就能夠產生驗證碼,並且存好Session等待驗證,而準備lblMsg來顯示驗證的訊息。驗證的相關程式碼如下:
Protected Sub Login1_Authenticate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles Login1.Authenticate
If String.Compare(Me.txtChkCode.Text.ToUpper, Session("CheckCode")) <> 0 Then
Me.lblMsg.Text = "驗證碼錯誤!!"
Else
If Membership.ValidateUser(Me.Login1.UserName, Me.Login1.Password) Then
FormsAuthentication.RedirectFromLoginPage(Me.Login1.UserName, Me.Login1.RememberMeSet)
End If
End If
'2018/5/10 增加:由於驗證圖形是透過圖形讀取時產生,如果不透過頁面重新讀取,驗證碼就不會變換,變成驗證碼是固定,這樣會讓機器人有可乘之機
'因此,無論驗證是否成功,立刻亂數修改驗證碼,讓原有的驗證碼失效
Session("CheckCode") = RdnGenCode()
End Sub
以下是簽名:
- 歡迎轉貼本站的文章,不過請在貼文主旨上加上【轉貼】,並在文章中附上本篇的超連結與站名【topcat姍舞之間的極度凝聚】,感恩大家的配合。
- 小喵大部分的文章會以小喵熟悉的語言VB.NET撰寫,如果您需要C#的Code,也許您可以試著用線上的工具進行轉換,這裡提供幾個參考
Microsoft MVP Visual Studio and Development Technologies (2005~2019/6) | topcat Blog:http://www.dotblogs.com.tw/topcat |