Design

Design
asp.net mvc

2017年4月8日 星期六

ASP.NET MVC AJAX AjaxAntiForgeryToken 防範CSRF

維基百科,自由的百科全書

跨站請求偽造英語:Cross-site request forgery),也被稱為 one-click attack 或者 session riding,通常縮寫為 CSRF 或者 XSRF, 是一種挾制用戶在當前已登錄的Web應用程式上執行非本意的操作的攻擊方法。[1] 跟跨網站指令碼(XSS)相比,XSS 利用的是用戶對指定網站的信任,CSRF 利用的是網站對用戶網頁瀏覽器的信任。

我們怎麼防止被外部網站攻擊我們的資料,廢話不多 就開始吧


我們先建立我們要在呼叫前的驗證
  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class AjaxValidateAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
    {

        public Task ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation)
        {
         
            if (actionContext == null)
            {
                throw new ArgumentNullException("HttpActionContext");
            }

            if (actionContext.Request.Method != HttpMethod.Get)
            {
             
                return ValidateAntiForgeryToken(actionContext, cancellationToken, continuation);
            }

            return continuation();
        }

        private Task ValidateAntiForgeryToken(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation)
        {
            try
            {
                string cookieToken = "";
                string formToken = "";
                IEnumerable tokenHeaders;

       
                if (actionContext.Request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
                {
                    string[] tokens = tokenHeaders.First().Split(':');
                    if (tokens.Length == 2)
                    {
                        cookieToken = tokens[0].Trim();
                        formToken = tokens[1].Trim();
                    }
                }
                AntiForgery.Validate(cookieToken, formToken);
            }
            catch (System.Web.Mvc.HttpAntiForgeryException ex)
            {
                actionContext.Response = new HttpResponseMessage
                {
                    StatusCode = HttpStatusCode.Forbidden,
                    RequestMessage = actionContext.ControllerContext.Request
                };
                return FromResult(actionContext.Response);
            }
            return continuation();
        }
        private Task FromResult(HttpResponseMessage result)
        {
            var source = new TaskCompletionSource();
            source.SetResult(result);
            return source.Task;
        }
    }



加在我們取資料的action上
        [HttpPost]
        [AjaxValidateAntiForgeryToken]
        public async Task GetAccountbyEmail()
        {
            var Email = new GetByMail();
            Email.Email = User.Identity.GetAccountEmail();

            var Request = await _accountService.GetByEmail(Email);

            return Request;
        }

我們再去建立要放在cshtml頁面的HtmlHelper去建立我們的Token
public static MvcHtmlString AjaxAntiForgeryToken(this HtmlHelper helper)
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            TagBuilder builder = new TagBuilder("div");
            string ForgeryToken = string.Concat(cookieToken,":", formToken);
            builder.MergeAttribute("id", "AntiForgery");
            builder.MergeAttribute("Value", ForgeryToken);
            builder.ToString(TagRenderMode.Normal);
            return  MvcHtmlString.Create(builder.ToString());

        }

然後在我們的cshtml頁面使用他 @Html.AjaxAntiForgeryToken()

 接著最重要的就是我們要在前端呼在我們的headers 加上剛剛在cshtml建立的token
this.http.get(url, { headers: { 'RequestVerificationToken': $("#AntiForgery").attr("value") } });

完成我們的驗證步驟 當進入頁面 會產生 token > 接著我們撈取資料時會針對herder上的token 去做驗證 > 接著要做的事情就可以自己處理了

沒有留言:

張貼留言