日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

Asp.net MVC中防止HttpPost重复提交

發(fā)布時(shí)間:2024/9/20 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Asp.net MVC中防止HttpPost重复提交 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

重復(fù)提交的場(chǎng)景很常見,可能是當(dāng)時(shí)服務(wù)器延遲的原因,如購物車物品疊加,重復(fù)提交多個(gè)訂單。常見的解決方法是提交后把Button在客戶端Js禁用,或是用Js禁止后退鍵等。在ASP.NET MVC 3?Web Application中 如何去防止這類HTTP-Post的重復(fù)提交呢? 我們可以借助Session,放置一個(gè)Token在View/Page上,然后在Server端去驗(yàn)證是不是同一個(gè)Token來判斷此次Http-Post是否有效。看下面的代碼:? 首先定義一個(gè)接口,便于擴(kuò)展。

public interface IPageTokenView {/// <summary>/// Generates the page token./// </summary>string GeneratePageToken();/// <summary>/// Gets the get last page token from Form/// </summary>string GetLastPageToken { get; }/// <summary>/// Gets a value indicating whether [tokens match]./// </summary>/// <value>/// <c>true</c> if [tokens match]; otherwise, <c>false</c>./// </value>bool TokensMatch { get; } }


定義一個(gè)Abstract Class,包含一個(gè)

public abstract class PageTokenViewBase : IPageTokenView {public static readonly string HiddenTokenName = "hiddenToken";public static readonly string SessionMyToken = "Token";/// <summary>/// Generates the page token./// </summary>/// <returns></returns>public abstract string GeneratePageToken();/// <summary>/// Gets the get last page token from Form/// </summary>public abstract string GetLastPageToken { get; }/// <summary>/// Gets a value indicating whether [tokens match]./// </summary>/// <value>/// <c>true</c> if [tokens match]; otherwise, <c>false</c>./// </value>public abstract bool TokensMatch { get; }}


接著是實(shí)現(xiàn)SessionPageTokenView類型,記得需要在驗(yàn)證通過后生成新的Token,對(duì)于這個(gè)Class是把它放到Session中。

public class SessionPageTokenView : PageTokenViewBase{#region PageTokenViewBase/// <summary>/// Generates the page token./// </summary>/// <returns></returns>public override string GeneratePageToken(){if (HttpContext.Current.Session[SessionMyToken] != null){return HttpContext.Current.Session[SessionMyToken].ToString();}else{var token = GenerateHashToken();HttpContext.Current.Session[SessionMyToken] = token;return token;}}/// <summary>/// Gets the get last page token from Form/// </summary>public override string GetLastPageToken{get{return HttpContext.Current.Request.Params[HiddenTokenName];}}/// <summary>/// Gets a value indicating whether [tokens match]./// </summary>/// <value>/// <c>true</c> if [tokens match]; otherwise, <c>false</c>./// </value>public override bool TokensMatch{get{string formToken = GetLastPageToken;if (formToken != null){if (formToken.Equals(GeneratePageToken())){//Refresh tokenHttpContext.Current.Session[SessionMyToken] = GenerateHashToken();return true;}}return false;}}#endregion #region Private Help Method/// <summary>/// Generates the hash token./// </summary>/// <returns></returns>private string GenerateHashToken(){return Utility.Encrypt(HttpContext.Current.Session.SessionID + DateTime.Now.Ticks.ToString());} #endregion

這里有到一個(gè)簡(jiǎn)單的加密方法,你可以實(shí)現(xiàn)自己的加密方法.?

public static string Encrypt(string plaintext) {string cl1 = plaintext;string pwd = string.Empty;MD5 md5 = MD5.Create();byte[] s = md5.ComputeHash(Encoding.Unicode.GetBytes(cl1));for (int i = 0; i < s.Length; i++){pwd = pwd + s[i].ToString("X");}return pwd; }

我們?cè)賮砭帉懸粋€(gè)Attribute繼承FilterAttribute, 實(shí)現(xiàn)IAuthorizationFilter接口。然后比較Form中Token與Session中是否一致,不一致就Throw Exception. Tips:這里最好使用依賴注入IPageTokenView類型,增加Logging 等機(jī)制?

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public sealed class ValidateReHttpPostTokenAttribute : FilterAttribute, IAuthorizationFilter {public IPageTokenView PageTokenView { get; set; }/// <summary>/// Initializes a new instance of the <see cref="ValidateReHttpPostTokenAttribute"/> class./// </summary>public ValidateReHttpPostTokenAttribute(){//It would be better use DI inject it.PageTokenView = new SessionPageTokenView();}/// <summary>/// Called when authorization is required./// </summary>/// <param name="filterContext">The filter context.</param>public void OnAuthorization(AuthorizationContext filterContext){if (filterContext == null){throw new ArgumentNullException("filterContext");}if (!PageTokenView.TokensMatch){//log...throw new Exception("Invaild Http Post!");}} }


還需要一個(gè)HtmlHelper的擴(kuò)展方法:

public static HtmlString GenerateVerficationToken(this HtmlHelper htmlhelper) {string formValue = Utility.Encrypt(HttpContext.Current.Session.SessionID+DateTime.Now.Ticks.ToString());HttpContext.Current.Session[PageTokenViewBase.SessionMyToken] = formValue;string fieldName = PageTokenViewBase.HiddenTokenName;TagBuilder builder = new TagBuilder("input");builder.Attributes["type"] = "hidden";builder.Attributes["name"] = fieldName;builder.Attributes["value"] = formValue;return new HtmlString(builder.ToString(TagRenderMode.SelfClosing)); }


將輸出這類的HtmlString:?

<input name="hiddenToken" type="hidden" value="1AB01826F590A1829E65CBD23CCE8D53" />

我們創(chuàng)建一個(gè)叫_ViewToken.cshtml的Partial View,這樣便于模塊化,讓我們輕易加入到具體View里,就兩行代碼,第一行是擴(kuò)展方法NameSpace

@using Mvc3App.Models; @Html.GenerateVerficationToken()

假設(shè)我們這里有一個(gè)簡(jiǎn)單的Login.cshtml,然后插入其中:
<form method="post" id="form1" action="@Url.Action("Index")"><p>@Html.Partial("_ViewToken")UserName:<input type="text" id="fusername" name="fusername" /><br />Password:<input type="password" id="fpassword" name="fpassword" /><input type="submit" value="Sign-in" /></p></form>
這里我們Post的Index Action,看Controller代碼,我們?cè)贗ndex上加上ValidateReHttpPostToken的attribute.


[HttpPost] [ValidateReHttpPostToken] public ActionResult Index(FormCollection formCollection) {return View(); }public ActionResult Login() {return View(); }

好的,完了,由于篇幅有限,單元測(cè)試代碼不貼了。讓我們運(yùn)行程序在IE中. 正常點(diǎn)擊Button后提交表單,此時(shí)按F5再次提交,看到這個(gè)提示框:



點(diǎn)擊Retry后,這時(shí)就會(huì)出現(xiàn)預(yù)期Exception,這里只是為了演示,實(shí)際中可能需要記錄日志,做異常處理。

Invaild Http Post!

Description:?An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.?Exception Details:?System.Exception: Invaild Http Post!?
有興趣您可以自己試一下,希望對(duì)您Web開發(fā)有幫助。

總結(jié)

以上是生活随笔為你收集整理的Asp.net MVC中防止HttpPost重复提交的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。