<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      多頁面驗證碼沖突的解決辦法

      場景:

      某網站在許多地方需要驗證碼(例如:文件下載、發表留言等),所以用戶可能會打開多個包含驗證碼的頁面,根據常規驗證碼實現的思路,會導致沖突,只有最后一個頁面的驗證碼是可以用的,如何解決?

       

      其他網站的“解決辦法”:

      1、大部分網站,例如中國移動和中國電信的網站并沒有做任何優化,只有最后打開的一個網頁的驗證碼可用。如果這個驗證碼僅僅是用來驗證登陸的話問題不大。

      2、中國聯通的網站用一個小技巧解決了這個問題。給輸入驗證碼的輸入框綁定一個事件,每次獲得焦點的時候獲取一個新的驗證碼,這樣也就保證了,不管你在哪輸入驗證碼,每當你想要輸入的時候,它就給你一個最新的。

      3、xun6網盤的解決方案,用了一個key,給每一個驗證碼標一個key,這樣也就防止了沖突。

      image

       

      基本思路:

      我的解決方案應該和xun6的差不多,也是用了一個key,來代表本次會話,然后根據這個key去得到驗證碼。

      基本思路如下:

      image

      左:直接打開或刷新頁面時的流程

      中:不刷新頁面更換驗證碼的流程

      右:驗證流程

       

      關鍵:如果一個表單中有驗證碼,那么也需要在這個表單中存儲一下這個會話的ID,用來對應服務端的驗證碼

       

      驗證碼管理類——概況:

      可以看到,這個過程中,流程是固定的,所以完全自己設計一個類,來實現這個“復雜”的過程,因為我懶得每次都重寫一遍~

      (懶人才能促進科技的發展,哈哈~)

       

      直接看類設計圖吧,關鍵看一下公有方法(我隱藏了字段,屬性和私有方法,因為這些只是浮云~):

      image

       

      驗證碼管理類——用法:

      1、IAuthCodeBuilder接口,這是什么?因為驗證碼生成的步驟區別很大,大家自由一套辦法,所以需要傳入一個驗證碼構造者來生成和輸出驗證碼,實現該接口即可。

      image

       

      2、再看構造函數和Initialize方法,無參數的構造函數&Initialize函數,需要配合Unity來使用,用來實現依賴注入。如果你不想使用依賴注入,可以修改我的源碼,把他們上面的Attribute去掉即可~

       

      3、另外幾個構造函數,IAuthCodeBuilder前面已經解釋過了,另外一個字符串是什么?因為最終是以字典的形式保存在Session中的,所以需要有個名字,默認是"AuthCode”。

       

      4、關鍵函數之:Create

      根據上面生成圖片的流程圖,在此過程中,得到了會話ID后需要調用此函數,把會話ID和驗證碼保存到Session中。

       

      5,、關鍵函數之:Authorize

      提交表單后,根據用戶輸入的驗證碼和會話ID,判斷是否正確。

       

      驗證碼管理類——Asp.net 用法:

      1、后端代碼 Default.aspx.cs

      public partial class _Default : System.Web.UI.Page
      {
          public string imageURL;
          public string sessionID;
      
          protected void Page_Load(object sender, EventArgs e)
          {
              var ticks = DateTime.Now.Ticks.ToString();
              imageURL = "AuthCode.ashx?id=" + ticks;
              sessionID = ticks;
          }
      
          protected void Button1_Click(object sender, EventArgs e)
          {
              AuthCodeManager am = new AuthCodeManager(new AuthCodeBuilder());
              Response.Write("<script>alert('" + am.Authorize(Request["sessionID"], TextBox1.Text).ToString() + "');</script>");
              TextBox1.Text = "";
          }
      }

      生成:

      這里的圖片和隱藏的input,盡量不要用服務端控件,服務端控件會導致一個問題:傳送門

      另外,這里的寫法是一種前端頁面和后端代碼的傳值方法,這樣寫感覺和MVC的ViewData有異曲同工之妙~

      每次頁面刷新都需要生成新的驗證碼,不管是Get還是Post,所以寫在Page_Load函數中,并且不需要判斷IsPostBack

       

      驗證:

      驗證的過程很簡單,從表單中讀取會話ID和用戶輸入的驗證碼,然后去驗證一下即可。

       

      2、前端頁面 Default.aspx

      <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
      <img id="AuthImage" src="<%=imageURL %>" alt="Alternate Text" onclick="javascript:Refesh();"/>
      <input type="hidden" id="sessionID" name="sessionID" value="<%=sessionID %>" />
      <script type="text/javascript">
          function Refesh() {
              var ticks = new Date().getTime();
              document.getElementById('AuthImage').setAttribute('src', 'authcode.ashx?id=' + ticks);
              document.getElementById('sessionID').value = ticks;
          }
      </script>

      圖片:讀取后端代碼中的圖片地址

      會話ID:同上 圖片的onclick事件:隨機生成一個字符串,然后修改圖片的地址和會話ID,瀏覽器檢測到圖片地址變了,自動讀取新的圖片


      3、圖片 AuthCode.ashx

      public class AuthCode : IHttpHandler, IRequiresSessionState
      {
          public void ProcessRequest(HttpContext context)
          {
              string id = context.Request["id"];
              AuthCodeManager am = new AuthCodeManager(new AuthCodeBuilder());
              context.Response.ContentType = "image/jpeg";
              context.Response.Clear();
              context.Response.BinaryWrite(am.Create(id).ToArray());
          }
      
          public bool IsReusable
          {
              get
              {
                  return false;
              }
          }
      }
      

      AuthCodeBuilder:這是一個繼承了IAuthCodeBuilder借口的類,大家可以自己寫,也可以參考我里面的源代碼

      流程:和上面說的一樣

      IRequiresSessionState:這個,比較糾結了,必須繼承這個借口,才可以調用 HttpContext.Current.Session,詳細請看:傳送門

       

      4、運行一下吧!

      image 

      打開2個頁面,左邊的先打開,右邊的后打開

       

       

      image 

      在先打開的頁面中輸入驗證碼,沒有沖突哦~

       

       

      驗證碼管理類——MVC 用法:

      1、后端代碼 HomeController.cs

      public class HomeController : Controller
      {
          public ActionResult Index()
          {
              Bind();
              ViewData["Message"] = "歡迎使用 ASP.NET MVC!";
      
              return View();
          }
      
          [HttpPost]
          public ActionResult Index(string sessionID,string code)
          {
              Bind();
              AuthCodeManager am = new AuthCodeManager(new AuthCodeBuilder());
              if (am.Authorize(sessionID, code))
              {
                  Response.Write("<script>alert('成功!');</script>");
              }
              else
              {
                  Response.Write("<script>alert('失敗!');</script>");
              }
              return View();
          }
      
          public ActionResult AuthCode(string id)
          {
              AuthCodeManager am = new AuthCodeManager(new AuthCodeBuilder());
              return File(am.Create(id).ToArray(), "image/jpeg");
          }
      
          protected void Bind()
          {
              var ticks = DateTime.Now.Ticks.ToString();
              ViewData["imageURL"] = "home/authcode/" + ticks;
              ViewData["sessionID"] = ticks;
          }
      }
      

      其中,包含了每次刷新頁面都重新生成驗證碼(Bind方法)、驗證和圖片生成(AuthCode方法)


         2、前端頁面 Index.aspx

      <%using (Html.BeginForm())
        {%>
      <input type="text" name="code" value="" />
      <img id="AuthImage" src="<%=ViewData["imageURL"] %>" alt="Alternate Text" onclick="javascript:Refesh();" />
      <input type="hidden" id="sessionID" name="sessionID" value="<%=ViewData["sessionID"] %>" />
      <script type="text/javascript">
          function Refesh() {
              var ticks = new Date().getTime();
              document.getElementById('AuthImage').setAttribute('src', 'home/authcode/' + ticks);
              document.getElementById('sessionID').value = ticks;
          }
      </script>
      <input type="submit" name="submit" value="提交" />
      <%}%>
      

      基本和Asp.net的一樣,只是針對MVC修改了一下

       

      可擴展性:

      公布源碼,大家覺得我有寫的不好的地方,可以直接修改。但是我也考慮到了可擴展性。

      比如,設置會話ID和得到會話ID都是后端代碼執行了,不知道大家有沒有更好的解決方案?

      所以我在寫Create和Authorize這兩個方法時重寫了兩個缺少sessionID參數的重載

       

      /// <summary>
      /// 得到請求ID
      /// </summary>
      /// <returns></returns>
      protected virtual string GetSessionID()
      {
          throw new NotImplementedException("請重寫該方法后再調用!");
      }
      
      /// <summary>
      /// 自動獲取當前請求ID的驗證,請重寫GetSessionID()方法后再調用!
      /// </summary>
      /// <param name="authcode">驗證碼</param>
      /// <returns>是否通過</returns>
      public virtual bool Authorize(string authcode)
      {
          return Authorize(GetSessionID(), authcode);
      }

      他們會調用GetSessionID這個虛方法,然后在調用多參數的重載方法。

      使用的時候需要繼承我的類,重寫GetSessionID這個方法。

       

      另外幾個擴展點和這個差不多,大家看源碼就可以了~

       

      后記:

      F&Q:

      Q:如果一個人打開了N多頁面怎么辦?

      A:針對這個,我主要采取了2個手段:

      1、只要這個會話ID驗證了,就刪除

      2、如果有人不停刷新頁面,這個會話ID無法被正常刪除,所以會話ID列隊我設置了最大程度,超過最大長度則清理(沒人會打開1000多個頁面吧? - -|,就算打開了1000多個,那丟失了幾個也很正常了~)

       

      Q:安全性?

      A:客戶端只能得到一個會話ID,這個會話ID雖然和真實的驗證碼有一對一的映射,但是這個映射在服務端。而且,同一個圖片地址,每次調用都會生成一個新的驗證碼。

       

      本文寫了2個多小時,喜歡的朋友請幫忙點一下支持~謝謝!

       

      最后,也是最重要的:源代碼&示例程序下載

      posted @ 2010-10-19 18:11  Dozer  閱讀(5105)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 亚洲日本欧洲二区精品| 国内不卡一区二区三区| 亚洲精品国模一区二区| 国产精品黄色精品黄色大片| 纯肉高h啪动漫| 岛国岛国免费v片在线观看| 无码乱人伦一区二区亚洲| 欧美大bbbb流白水| 独山县| 玛曲县| 啊轻点灬大JI巴太粗太长了在线| 2021国产成人精品久久 | 激情伊人五月天久久综合| 在线观看视频一区二区三区| 91精品国产老熟女在线| 国产精品午夜精品福利| 91亚洲精品一区二区三区| 女人张开腿让男人桶爽| 亚洲人成网线在线播放VA| 久久综合给合久久狠狠狠88| 图片区偷拍区小说区五月| 国产精品福利自产拍久久| 高清无码午夜福利视频| 国产精品永久免费无遮挡| 在线涩涩免费观看国产精品| 亚洲久悠悠色悠在线播放| 日韩人妻无码一区二区三区| 在办公室被c到呻吟的动态图| 国产亚洲一区二区三区成人| 久久精品免视看国产成人| 欧美综合婷婷欧美综合五月 | 亚洲国产精品一区二区第一页| 日本夜爽爽一区二区三区| 午夜福利片一区二区三区| julia无码中文字幕一区| 国内精品久久久久电影院| 宝贝腿开大点我添添公视频免| 欧美乱码伦视频免费| 乱码午夜-极品国产内射| 野花在线观看免费观看高清| 亚洲人妻一区二区精品|