.NET ã§ã® CAPTCHA ã€ã¡ãŒãžã®äœæ
Experience Level - Intermediate
ããã¯ãèªåã§ç°¡åãªãã®ãäœæããæ¹æ³ã§ããæãè€éã§ã¯ãªããããããŸããããå°ãªããšãè¿œå ã®ã»ãã¥ãªãã£å±€ãæäŸããåžžã«å€åããçµæã»ãããæäŸããŸãã
ããã¯ãVB.NET ãš MVC ããŒãž ã«ãŒãã£ã³ã°ã䜿çšã㊠SQL ã§æ§ç¯ãããŠããŸãã
ãŸãããã¹ãŠã®çµæãæ ŒçŽãã SQL ããŒãã«ãäœæããå¿ èŠããããŸãã䜿çšé »åºŠã®é«ãã·ã¹ãã ã§ã¯ãGUID ã«ã€ã³ããã¯ã¹ãäœæããå¿ èŠããããŸãã
Create Table
CREATE TABLE [dbo].[captcha]([captchaGUID] [varchar](36) NOT NULL,[captchaValue] [varchar](10) NULL,[captchaDateAdded] [datetime] NULL,[captchaDateGuessed] [datetime] NULL)
ãµãŒãã¹ããŒãžãè¿œå
次ã«ãã©ã³ãã ãªæåãçæããé¢æ°ãäœæããŸããäžéšãããèŠããšãã³ãŒãã¯ããã€ãã®æ°å€ã«å¯ŸããŠç©ºã®æååãè¿ããŸãããã®ããã«ããŠãçæãããå€ã¯åžžã«ããŸããŸãªé·ãã«ãªããŸãã
å€ãšã㊠40 ã䜿çšããçç±ã¯ãæåå (é·ã 32) ã空çœå€ãè¿ã確çã 5 åã® 1 ã«ããããã§ãã
Random Letter Function
CREATE FUNCTION [dbo].[GetLetter](@MyInt INT) RETURNS VARCHAR(1) AS BEGINRETURN (SELECT REPLACE(SUBSTRING('ABCDEFGHJKMNPQRTUVQXYZ0123456789', @MyInt,1),'_',''))ENDGOSELECT dbo.GetLetter(ROUND(RAND()*40,0))
ãµãŒãã¹ããŒãžãè¿œå
ããã§ãã¬ã³ãŒãã Web ãµã€ãã«éãè¿ãããã®ã¹ãã¢ã ããã·ãŒãžã£ãäœæããŸããããã¯ãæšæž¬ããããã£ããã£ãçæãããåé€ãããå Žæã§ããããŸãããã®ã³ãŒãã§ã¯ã30 ååŸã«åé€ãããŸãã
é¢æ°ã 10 å以äžåŒã³åºããŠå€ãé£çµããå€ãæšæž¬å€ãåé€ããŸããStored Procedure
CREATE PROC [dbo].[NewCaptchaValue] AS BEGINWHILE (SELECT COUNT(*) FROM captcha WHERE captchaDateGuessed IS NULL)<150BEGIN
INSERT INTO captcha(captchaGUID,captchaValue,captchaDateAdded)SELECT NEWID(),dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0))+dbo.GetLetter(ROUND(RAND()*40,0)),GETDATE()ENDDELETE FROM captcha WHERE captchaDateGuessed<DATEADD(MINUTE,-30,GETDATE())DECLARE @Newcaptcha VARCHAR(36)=(SELECT TOP 1 captchaGUID FROM captcha WHERE captchaDateGuessed IS NULL)SELECT @NewcaptchaEND
ãµãŒãã¹ããŒãžãè¿œå
Pass/Fail ã®æååãéãè¿ãããšã«ããŸããã
Stored Procedure
CREATE PROC [dbo].[CaptchaValue](@captchaGUID VARCHAR(36),@captchaValue VARCHAR(10)) AS BEGINDECLARE @CaptchaValueDB VARCHAR(10)=(SELECT captchaValue FROM captcha WHERE captchaGUID=@captchaGUID)DECLARE @Newcaptcha VARCHAR(36)UPDATE captcha SET captchaDateGuessed=GETDATE() WHERE captchaGUID=@captchaGUIDIF @captchaValue=@CaptchaValueDBBEGINSET @Newcaptcha='Pass'ENDIF @captchaValue<>@CaptchaValueDB OR @CaptchaValueDB IS NULLBEGINSET @Newcaptcha='Fail'ENDSELECT @NewcaptchaEND
Visual Studio ã§ã¢ã«ãã㌠ãããžã§ã¯ãã«åãæ¿ãã
ããã«åŸãã¹ãããã€ãã®ã¹ããã
- ãããžã§ã¯ãã«ãŸã ãªãå Žåã¯ãã¹ã¯ãªãŒã³ã·ã§ããã«åŸã£ãŠ App_Code ãã©ã«ããŒãè¿œå ããŸãã
- App_Code ãã©ã«ããŒã§ããŠã¹ã®å³ãã¿ã³ãæŒãã[è¿œå ] > [ã¯ã©ã¹] ãéžæããŸãã
- ãããã¢ããã衚瀺ãããŸãããã®ã¯ã©ã¹ã Captcha.vb ãšåŒã³ãŸãã
ãã®æ°ããé ç®ãå³ã¯ãªãã¯ããããããã£ãéžæããŸãã
Public Class 宣èšã®äžã«ã次ã®åç §ãè¿œå ããŸãã
Imports System.Drawing
Visual Studio ã§ã¢ã«ãã㌠ãããžã§ã¯ãã«åãæ¿ãã
Private Shared Function GenerateLineNumberY() As Integer Dim ret As New Integer ret = (6 * Right((Rnd() * Rnd() * Rnd()), 1)) + 2 Return ret End Function Private Shared Function GenerateLineNumberX() As Integer Dim ret As New Integer ret = (6 * Right((Rnd() * Rnd() * Rnd()), 1)) + 2 Return ret End Function
Visual Studio ã§ã¢ã«ãã㌠ãããžã§ã¯ãã«åãæ¿ãã
Private Shared Function GenerateLineNumberSpace() As Integer Dim ret As New Integer ret = (Right(Rnd(), 1)) + 13 Return ret End Function Private Shared Function GenerateLineNumberHeight() As Integer Dim ret As New Integer ret = (2 * Right((Rnd() * Rnd() * Rnd()), 1)) + 1 Return ret End Function
Visual Studio ã§ã¢ã«ãã㌠ãããžã§ã¯ãã«åãæ¿ãã
Private Shared Function GenerateRandomPenColor() As System.Drawing.Pen Dim mypen As New Pen(Brushes.Cyan) Dim ret As New Integer ret = Right((Rnd() * Rnd() * Rnd()), 1) Select Case ret Case 5, 0, 1 mypen.Color = Color.DarkGray Case 6, 2 mypen.Color = Color.DarkRed Case 7, 3, 9 mypen.Color = Color.DarkOliveGreen Case 8, 4 mypen.Color = Color.DarkOrange End Select Return mypen End Function Private Shared Function GenerateRandomBrushColor() As System.Drawing.SolidBrush Dim myBrush As New SolidBrush(Color.Aqua) Dim ret As New Integer ret = Right((Rnd() * Rnd() * Rnd()), 1) Select Case ret Case 5, 0, 1 myBrush.Color = Color.DarkGray Case 6, 2 myBrush.Color = Color.DarkRed Case 7, 3, 9 myBrush.Color = Color.DarkOliveGreen Case 8, 4 myBrush.Color = Color.DarkOrange End Select Return myBrush End Function Public Shared Function GenerateCaptcha(CaptchaString As String) As Bitmap Dim Height As Integer = 60 Dim Width As Integer = 300 Dim objBitmap As Bitmap Dim objGraphics As Graphics
Dim oPoint As New PointF objBitmap = New Bitmap(Width, Height) objGraphics = Graphics.FromImage(objBitmap) 'Draw Background objGraphics.FillRectangle(Brushes.White, 0, 0, Width, Height) objGraphics.DrawRectangle(Pens.Black, 0, 0, Width - 2, Height - 2) 'Draw Text Dim oFont As New Font("Arial", 20) Dim spac As Integer = 5 Dim stringInt As Integer = 1 While stringInt <= CaptchaString.Length spac = spac + GenerateLineNumberSpace() oPoint = New PointF(spac, GenerateLineNumberHeight) objGraphics.DrawString(Mid(CaptchaString, stringInt, 1), oFont, GenerateRandomBrushColor, oPoint) stringInt = stringInt + 1 End While 'White Lines objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) objGraphics.DrawLine(Pens.White, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) 'Draw Lines objGraphics.DrawLine(GenerateRandomPenColor, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY()) objGraphics.DrawLine(GenerateRandomPenColor, GenerateLineNumberX, GenerateLineNumberY, Width - GenerateLineNumberX(), Height - GenerateLineNumberY())
objGraphics.DrawRectangle(Pens.Black, 0, 0, Width - 2, Height - 2)
Return objBitmap End Function
ãµã RegisterRoutes ãèŠã€ããŠãå éšã«æ°ããã«ãŒã (Routes.MapPageRoute) ãè¿œå ããŸãã
Sub RegisterRoutes(ByVal Routes As RouteCollection) Routes.MapPageRoute("Captcha", "Captcha/{GUID}", "~/Data/Images/CaptchaService.aspx") End Sub
ãµãŒãã¹ããŒãžãè¿œå
ããŒã¿ ãã©ã«ããŒãè¿œå ããã«ã¯ã次ã®ãªãã·ã§ã³ã䜿çšããŸãã
- ClaytabaseAcademy ãå³ã¯ãªãã¯ãã[è¿œå ] > [æ°ãããã©ã«ããŒ] ãªãã·ã§ã³ã䜿çšããŠããã©ã«ããŒã« Data ãšããååãä»ããŸãã
- ããã§ãImages ãšããååã®å¥ã®ãã©ã«ããŒãããŒã¿ ãã©ã«ããŒã«è¿œå ããŸãã
- 次ã«ãCaptchaService.aspx ãšãã Web ãã©ãŒã ã Images ãã©ã«ããŒã«è¿œå ããŸãã
ãã®ããŒãžã¯ãå ã»ã©äœæããã«ãŒã ãã³ãã©ã«ãã£ãŠåŒã³åºãããŸãã
Replace Code
Imports System.Data.SqlClientImports ClaytabaseAcademy.GlobalVariablesImports ClaytabaseAcademy.CaptchaImports System.DrawingImports System.Drawing.ImagingPublic Class CaptchaService Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim captchaguid As String = RouteData.Values("GUID").ToString Dim con As New SqlConnection(ConStr) Dim com As New SqlCommand("SELECT captchaValue FROM captcha WHERE captchaGUID='" + captchaguid + "'", con) con.Open() Dim CaptchaBitmap As Bitmap = GenerateCaptcha(com.ExecuteScalar) con.Close() Response.ClearContent() Response.ContentType = "image/bmp" CaptchaBitmap.Save(Response.OutputStream, ImageFormat.Gif) End SubEnd Class
ãµãŒãã¹ããŒãžãè¿œå
Claytabase Academy ãå³ã¯ãªãã¯ã㊠[è¿œå ] > [æ°ãããã©ã«ããŒ] ãéžæãããããžã§ã¯ãã®ã«ãŒãã« Pages ãšããååã®æ°ãããã©ã«ããŒãäœæããŸãã
CaptchaView ãšããæ°ãã Web ãã©ãŒã ãè¿œå ããŸãã
æ°ãã Web ããŒãžãäœæããã€ã¡ãŒãž ã³ã³ãããŒã«ãããã¹ã ããã¯ã¹ããã¿ã³ãhiddenfieldãããã³ã©ãã«ããã©ãã°ãããã以äžã®ã³ãŒããããŒãžã®æ¬æ (HTML éšå) ã«ã³ããŒããŸãã<body> <form id="form1" runat="server" style="margin:100px auto;width:300px;padding:10px;background-color:#fff;box-shadow:0 0 3px 0 #222;border-radius: 8px;"> <div style="text-align:center;"> <asp:Image ID="CaptchaImage" runat="server" /> </div> <div style="text-align:center;"> <asp:TextBox ID="captchaEntered" runat="server"></asp:TextBox> </div> <div style="text-align:center;"> <asp:Button ID="captchaSubmit" runat="server" Text="Submit" style="margin:5px auto"/> <asp:HiddenField ID="captchaGuid" runat="server" /> </div> <div style="text-align:center;"> <asp:Label ID="captchaResult" runat="server" Text=""></asp:Label> </div> </form></body>
æåŸã®ã¹ãããã¯ãã³ãŒããæ©èœããããšããã¹ãããããšã§ãããã®ããã«ã¯ãã³ãŒã ããã€ã³ã (å³ã¯ãªã㯠> ãã¥ãŒ ã³ãŒã) ã«ç§»åããã³ãŒã ããã€ã³ãã以äžã®ãã®ã«æŽæ°ããå¿ èŠããããŸãã
ããã«ãããããŒãžã®èªã¿èŸŒã¿æã«å®è¡ããããµããšãè¿œå ãããã¿ã³ã®ã¯ãªãã¯ãåŠçããå¥ã®ãµããäœæãããŸãã
Imports System.Data.SqlClientImports ClaytabaseAcademy.GlobalVariablesPublic Class CaptchaView Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load If Not IsPostBack Then Using con As New SqlConnection(ConStr) Using com As New SqlCommand("EXEC dbo.NewCaptchaValue", con) con.Open() Dim Captcha As String = com.ExecuteScalar captchaGuid.Value = Captcha CaptchaImage.ImageUrl = "/Captcha/" + Captcha End Using End Using End If End Sub Protected Sub GetCaptcha(sender As Object, e As EventArgs) Handles captchaSubmit.Click If IsPostBack Then Using con As New SqlConnection(ConStr) Dim valStr As String = Replace(captchaEntered.Text, "'", "''") Dim valGUID As String = Replace(captchaGuid.Value, "'", "''") Response.Write("valStr: " + valStr + "<br>") Response.Write("valGUID: " + valGUID + "<br>") Using com As New SqlCommand("EXEC CaptchaValue '" & valGUID & "','" & valStr & "'", con) con.Open() Dim res As String = com.ExecuteScalar() captchaResult.Text = res End Using Response.Write("EXEC CaptchaValue '" & valGUID & "','" & valStr & "'") End Using End If End SubEnd Class
Test that it has worked by select Build > Build Solution from the Top Menu
You should now be able to test this in a number of ways;- Click on Debug when on the relevant page
- Right Mouse button on the item within the project explorer and selecting View in Browser
- Right Mouse button on the page and select View in Browser
Claytabaseã«ãããŠã§ããµã€ãã®ãã¶ã€ã³
ããã¯ãåœç€Ÿã® Web ãµã€ã ãã¶ã€ã³ ãµãŒãã¹ã®äžéšã§ãããåžå Žã§æãé«éã§æé©åãããã·ã¹ãã ã® 1 ã€ã§ãã Ousia ã³ã³ãã³ã管çã·ã¹ãã ã³ãŒãããå€æŽãããã³ãŒãã®ã»ã¯ã·ã§ã³ã§ãã
ãããã¯ãçŽÂ£500ããå§ãŸããµã€ãã§å©çšã§ããŸã.