پیاده سازی AntiForgery Token توسط AJAX POST در MVC

پنجشنبه 25 تیر 1394

در این مقاله به نحوه پیاده سازی AntiForgery توسط AJAXPOST در MVC می پردازیم.

پیاده سازی AntiForgery Token توسط AJAX POST در MVC

AntiForgery Token برای پیاده سازی SCRF لازم است . SRCF مخفف [Cross- site Request Forgery] است که این روش بسیار ساده است که در آن هکر از اعتماد یک وب سایت به یکی از کاربران استفاه می کند. به عبارت دیگر مثلا سایت به کاربر به دلیل اینکه با نام کاربری و رمز کلمه عبور معتبر وارد شده و با موفقیت شناسایی شده است را اعتماد می کندو اطلاعاتی که او ارسال می کند را به راحتی قبول می کند. به همین دلیل هکر تلاش می کند تا کاربرانی که به سایت وارد شده و شناسایی شده اند را ترغیب نماید تا بر روی لینکی که داده های موردنظر هکر را ارسال می کند ، کلیک کنند، بدون اینکه کاربر متوجه این امر شود.

در Token ، Master Page  توسط کد سرور و ذخیره آن به عنوان شی global JSON با ویژگی نام "RequsetVerificationToken" دریافت می کند و Token را به header در AjaxPOST پر میکند. در سمت سرور یک فیلتر برای دریافت token با ویژگی نام "RequestVerificationToken" و اعتبارسنجی ایجاد کنید.

مراحل پیاده سازی AntiForgery Token از طریق AJAXPOST در MVC :

مرحله اول : دریافت مقدار Token در MasterPage از طریق کد سرور

@{
    string cookieToken, formToken;
    AntiForgery.GetTokens(null, out cookieToken, out formToken);
    var tokenHeaderValue = cookieToken + ":" + formToken;
}

token : cookietoken  در داخل یک cookie ذخیره می شود

token : formtoken به صفحه شما برای فرمها ارسال شده است

;()AntiForgery.GetTokens : مقدار token در داخل متغیر cookietoken و formtoken ذخیره میشود .

کد بالا را در Master page یا صفحه ای که antiforgery token نیاز است، اضافه کنید.

مرحله دوم : تعیین مقدار token به عنوان متغیر Global در jQuery

<script type="text/javascript">
        var TOKENHEADERVALUE = '@tokenHeaderValue';
</script >

tokenHeaderValue@ در متغیر "TOKENHEADERVALUE" ذخیره می شود.

کد بالا را در صفحه ای که در مرحله اول ایجاد کردید، قرار بدهید.

مرحله سوم : قراردادن Ajax با Header

$(document).ready(function () {
        $.ajaxSetup({
            headers: {
                'RequestVerificationToken': TOKENHEADERVALUE
            },
        });
    });

در ({...})ajaxSetup.$ شی headers با خصوصیت 'RequestVerificationToken' که شامل مقدار Token از متغیر 'TOKENHEADERVALUE' قرار دهید. 

$.ajax({
url: url,// URL to the Action method
type: 'POST',//Type 'GET'/ 'POST'
contentType: 'application/json;charset=utf-8', // Content Type
data: dataObj,// Data to be sent as parameter
success: function (data) {alert('Success!');}, //Return to success property after 
                                               //successful return from the action method
error: function(data) { alert('Error!');}      //Return to error when there any error in Ajax call
});

به این ';({...})ajaxSetup.$' یک ویژگی 'headers' به بالا ajax.$ فراخوانی می شود. هر زمان Ajax فراخوانی می شود به محدوده ای که در آن ';({...})ajaxSetup.$' مشخص شده است.

مرحله چهارم : ایجاد یک روش فیلتر اعتبارسنجی

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ValidateCustomAntiForgeryTokenAttribute : FilterAttribute, IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //throw new NotImplementedException();
    }
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext != null && filterContext.HttpContext != null && 
			filterContext.HttpContext.Request != null &&
            !string.IsNullOrEmpty(filterContext.HttpContext.Request.HttpMethod)
            && string.Compare(filterContext.HttpContext.Request.HttpMethod, "POST", true) == 0)
        {
            ValidateRequestHeader(filterContext.HttpContext.Request);
        }      
    }

    private void ValidateRequestHeader(HttpRequestBase request)
    {
        string cookieToken = "";
        string formToken = "";

        IEnumerable<string> tokenHeaders = request.Headers.GetValues("RequestVerificationToken");
        if (tokenHeaders != null && tokenHeaders.Count() > 0)
        {
            string[] tokens = tokenHeaders.First().Split(':');
            if (tokens.Length == 2)
            {
                cookieToken = tokens[0].Trim();
                formToken = tokens[1].Trim();
            }

            System.Web.Helpers.AntiForgery.Validate(cookieToken, formToken);
        }
    }
}</string>

فیلتر ValidateCustomAntiForgeryTokenAttribute و ثبت در FilterConfig  به عنوان

;(()Filter.Add(new ValidateCustomerForgeryTokenAttribute را ایجاد کنید.

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new ValidateCustomAntiForgeryTokenAttribute());
    }
}

این کلاس در متغیر داخل پوشه ی App_Startfolder در project MVC وجود دارد.

مرحله پنجم : تعیین فیلتر در فراخوانی متد Actionدر AjaxPost 

[HttpPost]
[ValidateCustomAntiForgeryToken]
public JsonResult IndexSingle(string data)
{
    return Json(data, JsonRequestBehavior.AllowGet);
}

در اینجا فیلتر بررسی می شود که اگر token معتبر بود در ادامه قبل از کنترل، action و اعتبارسنجی اجرا می شود . در غیر این صورت در متد مربوطه اجرا نمی شود.

کنترل جریان

1.  فراخوانی Ajax توسط دستور ;({})ajax.$ در خواست می شود

2. اگر فراخوانی Ajax معتبر بود ، فیلتر اجرا می شود.

در قسمت دستورات Control :

public void OnActionExecuting(ActionExecutingContext filterContext)
{
    if (filterContext != null && filterContext.HttpContext != null && 
         filterContext.HttpContext.Request != null &&
        !string.IsNullOrEmpty(filterContext.HttpContext.Request.HttpMethod)
        && string.Compare(filterContext.HttpContext.Request.HttpMethod, "POST", true) == 0)
    {
        ValidateRequestHeader(filterContext.HttpContext.Request);
    }  
}

3. در شرط ()IF ، بررسی می کند که آیا درخواستی که به سرور ارسال شده در Ajaxpost وجود دارد یا نه، اگر True  بود سپس متد (...ValidateRequestHeader(filterConte با درخواست به عنوان پارامتر فراخوانی می شود.

private void ValidateRequestHeader(HttpRequestBase request)
{
    string cookieToken = "";
    string formToken = "";

    IEnumerable<string> tokenHeaders = request.Headers.GetValues("RequestVerificationToken");
    if (tokenHeaders != null && tokenHeaders.Count() > 0)
    {
        string[] tokens = tokenHeaders.First().Split(':');
        if (tokens.Length == 2)
        {
            cookieToken = tokens[0].Trim();
            formToken = tokens[1].Trim();
        }

        System.Web.Helpers.AntiForgery.Validate(cookieToken, formToken);
    }
}</string>

4. در این متد، token از قسمت headers با ویژگی نام ["Requestverificationtoken"] تعیین شده در ({})ajaxSetup.$ جدا می شود.

5. قسمت مقدار token را برای دریافت cookieToken و formToken که با ':' جدا شده است.

6. token را به عنوان ;(System.Web.Helpers.AntiForgery.Validate(cookieToken, formToken اعتبارسنجی می کند.

اگر معتبر بود، کنترل به متد action از طریق .ajax.$ فرخوانی شده است.

 

فایل های ضمیمه

نرگس محمدی

نویسنده 36 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید