牛腩新聞釋出系統-驗證碼搞通了嗎?詳細註釋-秒懂!

00潤物無聲00發表於2015-07-31

    牛腩新聞釋出系統新增新聞和登入介面用到了驗證碼,生活中經常遇到形形色色的驗證碼,數字和字母的,12306圖片形式的,百度貼吧文字形式的等等。當時見得時候感覺很神奇,現在剛好學到了,感覺很有意思,接觸了BS之後,越來越多的網頁神祕的內容,會慢慢的被瞭解,這種渴望的感覺特別棒。見到了自己喜歡的那就應該認真的分析,理解驗證碼的產生,這裡說的是數字和字母型別的,從簡單的入手。

什麼是驗證碼,它是幹什麼的?

    驗證碼:是一種區分使用者是計算機還是人的公共全自動程式。可以防止:惡意破解密碼、刷票、論壇灌水,有效防止某個黑客對某一個特定註冊使用者用特定程式暴力破解方式進行不斷的登陸嘗試。

    學習驗證碼的生成知識,內容涉及到了HTML,JavaScript,CSS,還有C#語言程式碼。經過認真學習,整體上理清了各部分之間的實現關係。

HTML程式碼:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="login.aspx.cs" Inherits="Web.admin.login" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>後臺登陸-牛腩新聞釋出系統</title>

    <link href="../CSS/login.css" rel="stylesheet" />   <!--引用-->
    <script lang="javascript" type="text/javascript">
        function changeCode() {
            var imgNode = document.getElementById("vimg");     // 得到的是一個物件。根據網頁中 id=vimg 的元素; 
            imgNode.src = "hander/WaterMark.aspx?t=" + (new date()).valueOf();//這裡加個時間的引數防止瀏覽器。重新整理驗證碼字元;
        }

    </script>
</head>
<body>
    <form id="form1" runat="server">
        <!--CSS的可重用性-->
        <div id="loginfrm" class="round1">

            <h3>後臺登陸-牛腩新聞釋出系統</h3>

            <div id="login">
                <img src="../images/niunanlogo.jpg" alt="LOGO" class="login_logo" />
                <!--P是塊級元素換行-->
                <p>
                    使用者名稱:<asp:TextBox ID="txtName" runat="server" CssClass="textbox"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="請輸入使用者名稱!" Text="*" ControlToValidate="txtName"></asp:RequiredFieldValidator>
                </p>
                <p>
                    密__碼:<asp:TextBox ID="txtPassword" runat="server" TextMode="Password" CssClass="textbox"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="請輸入密碼!" Text="*" ControlToValidate="txtPassword"></asp:RequiredFieldValidator>
                </p>
                <p>
                    驗證碼:<img src="../handler/WaterMark.ashx" id="vimg" alt="" onclick="changCode()" />
                    <asp:TextBox ID="txtCode" runat="server" CssClass="textcode"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ErrorMessage="請輸入驗證碼!" Text="*" ControlToValidate="txtCode"></asp:RequiredFieldValidator>
                </p>
                <p>
                    <asp:Button ID="btnLogin" runat="server" Text="登陸" OnClick="btnLogin_Click" />
                    <asp:ValidationSummary ID="ValidationSummary1" runat="server" ShowMessageBox="true" ShowSummary="false" />
                </p>
            </div>

            <div id="footer">
                版權所有 &copy <a href="http://www.baidu.com" target="_blank">牛腩</a> & <a href="http://www.baidu.com" target="_blank">眾志網</a>
            </div>
        </div>
    </form>
</body>
</html>

    HTML程式碼中, 驗證碼:<img src="../handler/WaterMark.ashx" id="vimg" alt="" onclick="changCode()" /> 這裡<img> 元素向網頁中嵌入一幅影象。檔案字尾為.ashx的檔案,是一般處理程式生成的圖片引用過來。給他一個表示的id。當點選這個圖片的時候。onclick="changCode()"當點選按鈕時執行<head>中的一段 JavaScript。

這裡用到了兩個驗證控制元件;

    RequiredFieldValidator:用於使輸入控制元件成為一個必選欄位。通過該控制元件,如果輸入值的初始值未改變,那麼驗證將失敗。預設地,初始值是空字串 ("")。
Runat:該控制元件為伺服器控制元件;ErrorMessage:當驗證失敗時,在ValidationSummary控制元件中顯示的文字。Text=當驗證失敗時顯示的資訊;ControlToValidate:要驗證的控制元件的id;該控制元件通過ControlToValidate:屬性的值與要驗證控制元件的id相結合。
    ValidationSummary:用於在網頁、訊息框或在這兩者中內聯顯示所有驗證錯誤的摘要。在該控制元件中顯示的錯誤訊息是由每個驗證控制元件的 ErrorMessage 屬性規定的。
ShowMessageBox:布林值,指示是否在訊息框中顯示驗證摘要。彈出框中出現;
ShowSummary:布林值,規定是否顯示驗證摘要;

    這兩個驗證控制元件經常結合使用;

C#程式碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using BLL;
using Model;
using System.Web.Security;

namespace Web.admin
{
    public partial class login : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
        //登入按鈕
        protected void btnLogin_Click(object sender, EventArgs e)
        {
            //判斷驗證碼是否輸入正確;
            string code = txtCode.Text.Trim().ToUpper();
            string rigthCode = Session["Code"].ToString();  //從一般處理程式中產生,這裡獲得。

            if (code != rigthCode)<span style="white-space:pre">	</span>//判斷驗證碼字元和使用者輸入的驗證碼是否一致;如果不相等
            {
                //Response.Write("<script>alert('驗證碼輸入錯誤!')</script>");
                Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script lang='javascript' defer>alter('驗證碼輸入錯誤!');</script>");
                return;
            }
<span style="white-space:pre">	</span>    //如果相等;
            string name = txtName.Text .ToString();      //把頁面上文字框中的值賦給變數;
            string pwd = txtPassword.Text.ToString();

            //把密碼轉為MD5碼的形式;密碼暗碼;
            pwd = FormsAuthentication.HashPasswordForStoringInConfigFile(pwd, "MD5");
           
            bool b = LoginManager.Login(name, pwd);
            if (b)
            {
                //跳轉
                Session["admin"] = name;     //把使用者名稱給Session["admin"]程式以後會用到;

                Response.Redirect("categorymanager.aspx");//跳轉到該頁面;
            }
            else
            {//給出彈框提示;
                Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('登陸失敗,使用者名稱或者密碼錯誤!');</script>");
            }

        }
    }
}

C#程式碼的主要內容是判斷驗證碼輸入是否正確,驗證碼輸入正確之後,判斷使用者名稱和密碼是否正確,如果正確跳轉到Categorymanager頁面;


一般處理程式;

<pre name="code" class="csharp"><%@ WebHandler Language="C#" CodeBehind="WaterMark.ashx.cs" Class="Web.handler.WaterMark" %>

using System;
using System.Web;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Web.SessionState;

namespace Web.handler
{
    public class WaterMark : IHttpHandler, IRequiresSessionState  // 要使用session必須實現該介面,記得要匯入System.Web.SessionState名稱空間
    {

        public void ProcessRequest(HttpContext context)
        {
            string checkCode = GenCode(5);  // 產生5位隨機字元。根據下面的GenCode變數;
            context.Session["Code"] = checkCode; //將字串儲存到Session中,以便登入時進行驗證
            System.Drawing.Bitmap image = new System.Drawing.Bitmap(70, 22);    //是用於處理由畫素資料定義的影象的物件.<70*22>
            Graphics g = Graphics.FromImage(image);//Grapgics物件類似畫布或者一張紙,供其他物件在上面作圖。把圖片畫到該物件上;

            try
            {
                //生成隨機生成器
                Random random = new Random();

                //清空圖片背景色
                g.Clear(Color.White);

                // 畫圖片的背景噪音線
                int i;
                for (i = 0; i < 25; i++)
                {
                    int x1 = random.Next(image.Width);  //產生非負隨機數;
                    int x2 = random.Next(image.Width);
                    int y1 = random.Next(image.Height);
                    int y2 = random.Next(image.Height);
                    g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);  //例項化一個顏色的筆,然後根據這四個點 列印出頁面的邊框。
                }

                Font font = new System.Drawing.Font("Arial", 12, (System.Drawing.FontStyle.Bold)); //文字格式                                                             //LinearGradientBrush 建構函式 (Rectangle, Color, Color, Single, Boolean)根據矩形、起始顏色和結束顏色以及方向角度,建立 LinearGradientBrush 類的新例項。
               System.Drawing.Drawing2D.LinearGradientBrush brush = 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);//使用此圖形上下文的當前字型和顏色繪製由指定 string 給定的文字。checkCode為產生的5個隨機數,設定他們的格式;
               //畫圖片的前景噪音點  //DrawRectangle矩形的長度和寬度指的是象素之間的間隔數,因此如果要繪製DrawRectangle ( Pens.Black, 0,0, 5,4);最終會得到長為6個象素寬為5個象素的矩形框。 
                g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
                System.IO.MemoryStream ms = new System.IO.MemoryStream();//建立其支援儲存區為記憶體的流。  
                image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif); //將此 Image 以指定格式儲存到指定檔案。 S儲存圖片格式為 GIF. 
                context.Response.ClearContent();//ClearContent方法不僅刪除Response顯示輸出資訊而且還刪除Response頭資訊
                context.Response.ContentType = "image/Gif";//顯示為GIF的圖片格式; 
                context.Response.BinaryWrite(ms.ToArray());//輸出gif 圖片  
            }
            finally
            {
                g.Dispose();
                image.Dispose();
            }
        }

        /// <summary>
        /// 產生隨機字串
        /// </summary>
        /// <param name="num">隨機出幾個字元</param>
        /// <returns>隨機出的字串</returns>
        private string GenCode(int num)
        {                                                                  //根據前面引數,產生5個隨機數;   
            string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            char[] chastr = str.ToCharArray();
            // string[] source ={ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#", "$", "%", "&", "@" };
            string code = "";
            Random rd = new Random();
            int i;
            for (i = 0; i < num; i++)
            {
                //code += source[rd.Next(0, source.Length)];
                code += str.Substring(rd.Next(0, str.Length), 1);//Substring:字串的字字串、該子字串從指定的 beginIndex 處開始,直到索引 endIndex - 1 處的字元  
            }
            return code;

        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

    }
}

一般處理程式生成動態圖片和動態文字,這裡用來生成驗證碼圖片。


3個部分程式碼的各自分工:

    一般處理程式:用來生成5個隨機數,給隨機數設定好大小,前景噪音點,背景噪音點。最終形成一張GIF格式的圖片。

    HTML程式碼:對圖片前臺顯示格式的設定,以及點選圖片可以重新更換。因為是登入介面,介面上文字框和驗證碼中資訊的驗證。

    C#程式碼:與資料庫建立連線,對產生的驗證碼和使用者輸入的驗證碼進行對比判斷,驗證碼正確的基礎上進行登入資訊,使用者名稱和密碼的驗證。最終判斷是否可以登入。



總結:

    通過學習牛腩,分析驗證碼的整個流程,知道了驗證碼是怎麼產生的,對這部分內容比較感興趣,生活中處處需要驗證碼。隨著BS的學習,會掌握越來越多經常見到以前覺得神奇,不屬於自己的東西。解開神祕面紗,神奇的旅程。

相關文章