اشتراکها
اشتراکها
پروژه Prerender.io
طبق تحقیقاتی که انجام دادم اصلا Seo friendly نیست دلیلشم بر میگرده به نحوه محاسبه Page rank که همون اسمش مشخصه به محتواتی صفحه کار داره.
نظرات مطالب
خواندنیهای 16 اردیبهشت
سلام
خیلی ممنون لطف کردین
پایدار باشید
خیلی ممنون لطف کردین
پایدار باشید
اشتراکها
چهارسال گذشته چی بوده ام!
با سلام و خسته نباشید و تشکر از بابت مطالب مفیدتان
سوال بنده در مورد Angular اینه که آیا برای نوشتن سایتهای تجاری مفیده یا نه ،
چند مورد که من بهش فکر کردم و جایی نتونستم ازش نتیجه بگیرم موارد زیره که اگه راهنمایی کنید برای ادامه آموزش بهتر
1- ایا آوردن اطلاعات و محتویات سایت همراه اکشن درخواست صفحه بهتر نیست و باعث سرعت بیشتر سایت نمیشه؟(معمولا اطلاعات در ساختار فریمورک انگولا بعد از لود شدن همه htmlها و فایلهای js و با یک سرویس دریافت میشه "مثل لود کردن محتوی ایجکسی" که به نظرم به خاطر دو مرحله ای بودن کندی زیادی داره )
2- آیا در Seo تاثیر داره ؟ محتوا و روتینگها همه با ایجکس انجام میشه و نمیدونم گوگل این چیزا روی میفهمه یا نه
در کل ممنون میشه که بدونم شما اگه بخواید یه سایت مثلا همین سایتتون را از اول بنویسید آیا از این فریمورک استفاده میکنید یانه
نظرات مطالب
ساخت ربات تلگرامی با #C
با تشکر از این مطلب مفید. بنده هم چند روز پیش سری به مستندات تلگرام زدم و یه ربات با تمام قابلیت هاش طراحی کردم. در این مورد نکات کلی هست که انشاله مورد استفاده قرار بگیره.
به جای [bot-token] باید توکن ربات خودتون رو بذارید.
برای ایجاد ربات بهتره با کتابخانه پیشنهادی خود تلگرام کار کنید.(اینجا ) و یا اون رو از طریق Nuget دریافت کنید.
pm> Install-Package Telegram.Bot
درمورد دو روش کار با ربات باید بدونید که روش getUpdate فقط برای تست کردن پاسخگویی ربات بهتره استفاده بشه و اگراصرار به استفاده از این حالت دارید ربات شما نمیتونه به چندین کاربر پاسخ بده چون طبق این روش در هر لحظه برای مثال 10 آپدیت دریافت میشه این آپدیتها همون درخواستهای کاربرا هستن پس درخواست یازدهم باید صبر کنه تا 10 درخواست اول پاسخ داده بشن. حل شد؟
روش اصلی که شما برای ربات باید استفاده کنید همون Webhook هست اما این هم نکاتی داره. طبق قواعد تلگرام برای استفاده از این روش باید حتما ssl روی دامنه شما فعال باشه و شما هم باید یه وب سرویس برای پاسخگویی به درخواستها پیاده کنید.
برای دریافت ssl رایگان میتونید از CloudFlare استفاده کنید که اگر بگردید آموزش هاش هست و کار راحتیه
برای پیاده سازی وب سرویس اون هم با Web Api میتونید از این مثال استفاده کنید.
حالا بعد از اینکه ربات رو توی حالت getupdate طراحی و تست کردید میتونید اون رو به حالت webhook منتقل کنید.
نکته ای هم که وجود داره اینه که شما نمیتونید به طور همزمان برای یک ربات هم از webhook و هم از getupdate استفاده کنید !
پس برای زمانی که ربات رو در حالت webhook منتشر کردید ولی دوباره نیاز به تست و دیباگ دارید و میخواید از getupdate استفاده کنید باید حتما حالت webhook رو با استفاده از فراخوانی api زیر غیر فعال کنید (داخل آدرس بار مرورگر).
https://api.telegram.org/bot[bot-token]/setwebhook
بعد دوباره برای فعال کردن webhook میتونید فراخوانی زیر رو داشته باشید.
https://api.telegram.org/bot[bot-token]/setwebhook?url=https://yourdomain.example/api/webhook
مسیرراهها
ASP.NET MVC
- ASP.NET MVC #1
- ASP.NET MVC #2
- ASP.NET MVC #3
- ASP.NET MVC #4
- ASP.NET MVC #5
- ASP.NET MVC #6
- ASP.NET MVC #7
- ASP.NET MVC #8
- ASP.NET MVC #9
- ASP.NET MVC #10
- ASP.NET MVC #11
- ASP.NET MVC #12
- ASP.NET MVC #13
- ASP.NET MVC #14
- ASP.NET MVC #15
- ASP.NET MVC #16
- ASP.NET MVC #17
- ASP.NET MVC #18
- ASP.NET MVC #19
- ASP.NET MVC #20
- ASP.NET MVC #21
- ASP.NET MVC #22
- ASP.NET MVC #23
- ASP.NET MVC #24
- نحوه ارتقاء برنامههای موجود MVC3 به MVC4
- تغییرات بوجود آمده در Bundling and Minification -MVC4
- تغییرات بوجود آمده در Mobile Features-MVC4
- تغییرات بوجود آمده در Single Page Application (SPA)-MVC4
- تغییرات بوجود آمده در Razor -MVC4
- Globalization در ASP.NET MVC
- Globalization در ASP.NET MVC - قسمت دوم
- Globalization در ASP.NET MVC - قسمت سوم
- Globalization در ASP.NET MVC - قسمت چهارم
- Globalization در ASP.NET MVC - قسمت پنجم
- Globalization در ASP.NET MVC - قسمت ششم
- Globalization در ASP.NET MVC - قسمت هفتم
- بررسی تغییرات ASP.NET MVC 5 beta1
- مسیریابی (Routing) در ASP.NET MVC 5.x
- Attribute Routing در ASP.NET MVC 5
- قابلیت Attribute Routing در ASP.NET MVC 5
- یک تکنیک جالب در نحوه نام گذاری فیلدهای دیتابیس به منظور استفاده بهینه از فایلهای T4 در MVC 5
- نگاهی به هویت سنجی کاربران در ASP.NET MVC 5
- سفارشی کردن ASP.NET Identity در MVC 5
- افزودن تصدیق ایمیل به ASP.NET Identity در MVC 5
- ایجاد کپچایی (captcha) سریع و ساده در ASP.NET MVC 5
- توزیع یک اپلیکیشن ASP.NET MVC 5 روی Windows Azure
- معماری لایه بندی نرم افزار #1
- معماری لایه بندی نرم افزار #2
- معماری لایه بندی نرم افزار #3
- معماری لایه بندی نرم افزار #4
- CheckBoxList در ASP.NET MVC
- RadioButtonList در ASP.NET MVC
- مدیریت محل اعمال Google analytics در ASP.NET MVC
- استفاده از HttpGet در ASP.NET MVC، آری یا خیر؟!
- اثر وجود سشن بر پردازش موازی در ASP.NET
- استفاده از دکمههای CSS توئیتر در ASP.NET MVC
- نحوه صحیح تولید Url در ASP.NET MVC
- استفاده از OpenID در وب سایت جهت احراز هویت کاربران
- متدهای کمکی مفید در پروژههای asp.net mvc
- T4MVC : یکی از الزامات مدیریت پروژههای ASP.NET MVC
- مقدمه ای بر AutoMapper
- بهبود سرعت نمایش صفحات در ASP.NET MVC با حذف View Engines اضافی
- محدود کردن کاربرها به آپلود فایلهایی خاص در ASP.NET MVC
- ارسال فایل در ASP.NET MVC و اعتبار سنجی سمت کاربر
- فعال سازی قسمت ارسال فایل و تصویر ویرایشگر آنلاین RedActor در ASP.NET MVC
- معرفی پروژه Orchard
- مباحث تکمیلی مدلهای خود ارجاع دهنده در EF Code first
- سازگار کردن لینکهای قدیمی یک سایت با ساختار جدید آن در ASP.NET MVC
- CAPTCHAfa
- نکتهای در استفاده از AutoMapper
- یکپارچه سازی CKEditor با Lightbox
- تهیه خروجی RSS در برنامههای ASP.NET MVC
- ایجاد Helper سفارشی جهت نمایش ویدئو در ASP.NET MVC
- ساخت DropDownListهای مرتبط به کمک jQuery Ajax در MVC
- استفاده از دکمههای CSS توئیتر در ASP.NET MVC - قسمت دوم
- با ASP.MVC چه مزایایی را به دست خواهیم آورد
- نحوه اضافه کردن Auto-Complete به جستجوی لوسین در ASP.NET MVC و Web forms
- مقابله با پسوردهایی که ساده حدس زده میشوند
- غیرفعال کردن کش مرورگر در MVC
- Best Practice هایی برای ASP.NET MVC - قسمت اول
- چک لیست تهیه یک برنامه ASP.NET MVC
- استفاده از FluentValidation در ASP.NET MVC
- نحوه اجباری کردن استفاده از WWW در ASP.NET MVC
- نمایش رکوردها به ترتیب اولویت به کمک jQuery UI sortable در ASP.NET MVC
- کنترل عمومی فایلهای آپلودی در ASP.NET MVC
- هدایت خودکار کاربر به صفحه لاگین در حین اعمال Ajax ایی
- مدیریت سفارشی سطوح دسترسی کاربران در MVC
- بهبود SEO در ASP.NET MVC
- ایجاد قسمتهای Toggle در سایت با jQuery
- آشنایی و بررسی ابزار MiniProfiler
- استفاده از Flash Uploader در ASP.NET MVC
- استایل دهی به ستونهای header در WebGrid
- ELMAH و حملات XSS
- آموزش MEF#2(استفاده از MEF در Asp.Net MVC)
- نحوه استفاده از ViewModel در ASP.NET MVC
- مخفی کردن کوئری استرینگها در ASP.NET MVC توسط امکانات Routing
- توزیع پروژههای ASP.NET MVC بدون ارائه فایلهای View آن
- حذف هدرهای مربوط به وب سرور از طریق برنامه نویسی
- ایجاد helper برای Nivo Slider در Asp.net Mvc
- آشنایی با Fluent Html Helpers در MVC
- نحوه استفاده از افزونه Firebug برای دیباگ برنامههای ASP.NET مبتنی بر jQuery
- عدم امکان تغییر اطلاعات مدل در HTML Helpers پس از Postback در ASP.NET MVC
- اضافه کردن Watermark به تصاویر یک برنامه ASP.NET MVC در صورت لینک شدن در سایتی دیگر
- چگونگی رسیدگی به Null property در AutoMapper
- return File در ASP.NET MVC و نامهای یونیکد
- تولید SiteMap استاندارد و ایجاد یک ActionResult اختصاصی برای Return کردن SiteMap تولید شده
- نحوه ایجاد یک تصویر امنیتی (Captcha) با حروف فارسی در ASP.Net MVC
- الگوی PRG در ASP.NET MVC
- اعتبارسنجی سایتهای چند زبانه در ASP.NET MVC - قسمت اول
- آغاز به کار با Twitter Bootstrap در ASP.NET MVC
- استفاده از Twitter Bootstrap در کارهای روزمره طراحی وب
- نگاهی به اجزای تعاملی Twitter Bootstrap
- اعمال کلاسهای ویژه اعتبارسنجی Twitter bootstrap به فرمهای ASP.NET MVC
- ویرایش قالب پیش فرض Add View در ASP.NET MVC برای سازگار سازی آن با Twitter bootstrap
- استفاده از افزونه Typeahead مجموعه Twitter Bootstrap در ASP.NET MVC
- استفاده از modal dialogs مجموعه Twitter Bootstrap برای گرفتن تائید از کاربر
- Bundling and Minifying Inline Css and Js
- نمایش فرمهای مودال Ajax ایی در ASP.NET MVC به کمک Twitter Bootstrap
- MVC vs 3-Tier Pattern
- پلاگین جستجو با jquery و twitter bootstrap
- نمایش خطاهای اعتبارسنجی سمت کاربر ASP.NET MVC به شکل Tooltip به کمک Twitter bootstrap
- نمایش خطاهای اعتبارسنجی سمت کاربر ASP.NET MVC به شکل Popover به کمک Twitter bootstrap
- ساخت قالبهای نمایشی و ادیتور دکمه سه وضعیتی سازگار با Twitter bootstrap در ASP.NET MVC
- پیاده سازی Open Search در ASP.NET MVC
- Best Practice ی برای تأیید اعتبار کردن کاربران در ASP.NET MVC 4
- هدایت درخواست فایلهای استاتیک در ASP.NET MVC به یک کنترلر
- ModelBinder سفارشی در ASP.NET MVC
- ایجاد لینک با یک تصویر بوسیله Html Helper
- بارگزاری PartialView با استفاده از jQuery در زمان اجرا
- یافتن اکشن متدهای به اشتباه کش شده در ASP.NET MVC
- مروری مقدماتی بر ساخت برنامههای موبایل در MVC4
- اجرای برنامههای ASP.NET توسط Mono در Ubuntu
- اجرای برنامههای ASP.NET به کمک وب سرور Apache توسط Mono در Ubuntu
- فعالسازی استفاده از Session در ASP.NET MVC 4 API Controller ها
- ساخت منوهای چند سطحی در ASP.NET MVC
- طراحی ValidationAttribute دلخواه و هماهنگ سازی آن با ASP.NET MVC
- بهینه سازی برنامههای وب ASP.NET برای موتورهای جستجو (SEO)
- CheckBoxList برای فیلد Enum Flags مدل در ASP.Net MVC
- چطور مسیریابیهای ASP.NET MVC را دیباگ کنیم؟
- ذخیره TreeView ساخته شده توسط KendoUI در Asp.net MVC
- تنظیمات امنیتی Glimpse
- سفارشی سازی Binding یک خصوصیت از طریق Attributes
- Bundle کردن فایلهای LESS در MVC
- TwitterBootstrapMVC
- بررسی خطای Circular References در ASP.NET MVC Json Serialization
- ایجاد یک فیلتر سفارشی جهت تعیین Layout برای کنترلر و یا اکشن متد
- حذف فضاهای خالی در خروجی صفحات ASP.NET MVC
- جلوگیری از درج صفحات سایت در سایتی دیگر از طریق iframeها
- مشکل اعتبار سنجی jQuery validator در Bootstrap tabs
- افزودن هدرهای Content Security Policy به برنامههای ASP.NET
- امکان اعتبارسنجی با تاخیر در ASP.NET 4.5
- معرفی ASP.NET Identity
- متدهای احراز هویت در VS 2013
- توسعه اپلیکیشنهای ASP.NET با Windows Azure Active Directory
- ساخت یک اپلیکیشن ساده ToDo با ASP.NET Identity
- دریافت اطلاعات بیشتر از Social Providerها در VS 2013
- معرفی کتابخانه Postal برای ASP.NET MVC
- استفاده از Web Fonts در اپلیکیشنهای ASP.NET MVC
- استفاده از Awesomium.NET در برنامههای وب
- خواندن اطلاعات از سرور و نمایش آن توسط Angular در ASP.NET MVC
- آموزش Backload (آپلود چندین فایل به طور همزمان با آجاکس )
- یافتن اکشن متدهای Post ایی در ASP.NET MVC که فیلتر CSRF ندارند
- ایجاد سیستم وضعیت آب و هوا مانند گوگل (بخش اول)
- استفاده از #F در پروژههای MVC4
- توسعه کنترلر و مدل در F# MVC4
- تعامل با پایگاه داده با استفاده از EntityFramework در پروژههای F# MVC 4
- انجام کارهای زمانبندی شده در برنامههای ASP.NET توسط DNT Scheduler
- بررسی خروجی IsAjaxRequest در درخواستهای http$ توسط AngularJS
- بارگذاری فایلهای ایستا از پوشهی Views در ASP.NET MVC
- هدایت خودکار آدرسهای یافت نشد در یک سایت ASP.NET MVC به جستجوی سایت
- راههای متفاوت رندر لایهها در ASP.NET MVC
- پروژه Microsoft.AspNet.Mvc.Futures و تولید مسیرهای Strongly typed
- ASP.NET MVC و Identity 2.0 : مفاهیم پایه
- ارسال PingBack در ASP.NET
- Identity 2.0 : تایید حسابهای کاربری و احراز هویت دو مرحله ای
- مدیریت درخواستهای شرطی در ASP.NET MVC
- استفاده از Froala WYSIWYG Editor در ASP.NET
- استفاده از نگارش سوم Google Analytics API در سرویسهای ویندوز یا برنامههای وب
- بهینه سازی فایلهای js و css در برنامههای ASP.NET با استفاده از Combres - قسمت اول
- استفاده از pjax بجای ajax در ASP.NET MVC
- استفاده از افزونهی jsTree در ASP.NET MVC
- تفاوت ViewData و ViewBag و TempData و Session در MVC
- استفاده از چند فرم در کنار هم در ASP.NET MVC
- انجام کارهای پس زمینه در ASP.NET 4.5.2
- نمایش اخطارها و پیامهای بوت استرپ به کمک TempData در ASP.NET MVC
- صفحه بندی و مرتب سازی خودکار اطلاعات به کمک jqGrid در ASP.NET MVC
- فرمت کردن اطلاعات نمایش داده شده به کمک jqGrid در ASP.NET MVC
- فعال سازی و پردازش جستجوی پویای jqGrid در ASP.NET MVC
- استفاده از چند Routing در یک پروژه ASP.NET MVC بدون درد و خونریزی
- فعال سازی و پردازش صفحات پویای افزودن، ویرایش و حذف رکوردهای jqGrid در ASP.NET MVC
- رمزنگاری خودکار فیلدهای مخفی در ASP.NET MVC
- استفاده ازExpressionها جهت ایجاد Strongly typed view در ASP.NET MVC
- سفارشی سازی عناصر صفحات پویای افزودن و ویرایش رکوردهای jqGrid در ASP.NET MVC
- تهیه خروجی PDF و اکسل از حاصل جستجوی پویای jqGrid به کمک PDF Report
- Ajax.BeginForm و ارسال فایل به سرور در ASP.NET MVC
- آپلود فایل توسط فرمهای پویای jqGrid
- اختصاصی کردن Razor برای #C در MVC با استفاده از Extension Method
- روشی سریع برای ایجاد RSS و Sitemap در ASP.NET MVC
- اعتبارسنجی سفارشی سمت کاربر و سمت سرور در jqGrid
- OutputCache در ASP.NET MVC
- فعال سازی و پردازش Inline Add در jqGrid
- بهینه سازی سرعت یافت ویوها با سفارشی سازی Lookup Caching در Razor View Engine
- گروه بندی اطلاعات در jqGrid
- نمایش Subgrid در jqGrid
- ایجاد زیر گریدهای چند سطحی در jqGrid
- نمایش ساختارهای درختی توسط jqGrid
- سازگارسازی کلاسهای اعتبارسنجی Twitter Bootstrap 3 با فرمهای ASP.NET MVC
- اعتبارسنجی در فرمهای ASP.NET MVC با Remote Validation
- قالبهای سفارشی برای HtmlHelperها
- ارسال ویدیو بصورت Async توسط Web Api
- اعتبار سنجی سمت کاربر wysiwyg-editorها در ASP.NET MVC
- بررسی مقدمات کتابخانهی JSON.NET
- تنظیمات و نکات کاربردی کتابخانهی JSON.NET
- استفاده از JSON.NET در ASP.NET MVC
- LINQ to JSON به کمک JSON.NET
- آشنایی با چالشهای امنیتی در توسعه برنامههای تحت وب، بخش اول
- نمایش بلادرنگ اعلامی به تمام کاربران در هنگام درج یک رکورد جدید
- پیاده سازی Template تو در تو در AngularJS و ASP.NET MVC
- یکپارچه سازی سیستم اعتبارسنجی ASP.NET MVC با Kendo UI validator
- ساخت یک Form Generator ساده در MVC
- آشنایی با WebDav و نحوه استفاده از آن
- قابلیت Templated Razor Delegate
- اعمال تزریق وابستگیها به مثال رسمی ASP.NET Identity
- ثبت جزئیات استثناهای Entity framework توسط ELMAH
- نمایش بلادرنگ اعلامی به تمام کاربران در هنگام درج یک رکورد جدید به صورت notification
- کار با وب سرویس جاوایی تشخیص ایمیلهای موقتی در دات نت
- فراخوانی متدهای Controllerها در Viewهای ASP.NET MVC
- لغو اجرای یک اکشن فیلتر برای یک اکشن خاص در MVC
- کار با اسکنر در برنامههای تحت وب (قسمت اول)
- کار با اسکنر در برنامههای تحت وب (قسمت دوم و آخر)
- تبدیل یک View به رشته و بازگشت آن به همراه نتایج JSON حاصل از یک عملیات Ajax ایی در ASP.NET MVC
- آشنایی با ساختار ViewBag
- مدیریت سشنها در برنامههای وب به کمک تزریق وابستگیها
- خلاصهای از روشهای ارسال دادههای سمت سرور به کدهای جاوا اسکریپتی در ASP.NET MVC
- یکدست کردن "ی" و "ک" در ASP.NET MVC با پیادهسازی یک Model Binder
- حذف پردازش درخواستهای فایلهای استاتیک در متد Application_AuthenticateRequest
- دریافت خطاهای موجود در Viewهای ASP.NET MVC در زمان کامپایل
- پیاده سازی یک متد الحاقی برای تبدیل آدرس فیزیکی به آدرس مجازی (آدرس سرور)
- استفاده از Razor در فایلهای JavaScript و CSS
- عمومی سازی الگوریتمها با استفاده از Reflection
به ASP.NET Core 7، یک میانافزار جدید به نام Rate limiter اضافه شدهاست که امکان محدود سازی دسترسی به منابع برنامهی ما را میسر میکند. این میانافزار، طراحی جامع و مفصلی را دارد. به همین جهت نیاز است در ابتدا با مفاهیم مرتبط با آن آشنا شد و سپس به سراغ پیاده سازی و استفادهی از آن رفت.
چرا باید میزان دسترسی به منابع یک برنامهی وب را محدود کرد؟
فرض کنید در حال ساخت یک web API هستید که کارش ذخیره سازی لیست وظایف اشخاص است و برای مثال از یک GET /api/todos برای دریافت لیست ظایف، یک POST /api/todos برای ثبت و یک PUT /api/todos/{id} برای تغییر موارد ثبت شده، تشکیل میشود.
سؤال: چه مشکلی ممکن است به همراه این سه endpoint بروز کند؟
پاسخ: به حداقل چهار مورد زیر میتوان اشاره کرد:
- یک مهاجم سعی میکند با برنامهای که تدارک دیده، هزاران وظیفهی جدید را در چند ثانیه به سمت برنامه ارسال کند تا سبب خاتمهی سرویس آن شود.
- برنامهی ما در حین سرویس دهی، به یک سرویس ثالث نیز وابستهاست و آن سرویس ثالث، اجازهی استفادهی بیش از اندازهی از منابع خود را نمیدهد. با رسیدن تعداد زیادی درخواست به برنامهی ما تنها از طرف یک کاربر، به سقف مجاز استفادهی از آن سرویس ثالث رسیدهایم و اکنون برنامه، برای تمام کاربران آن قابل استفاده نیست.
- شخصی در حال دریافت اطلاعات تک تک کاربران است. از شماره یک شروع کرده و به همین نحو جلو میرود. برای دریافت اطلاعات کاربران، نیاز است شخص به سیستم وارد شده و اعتبارسنجی شود؛ یعنی به ازای هر درخواست، یک کوئری نیز به سمت بانک اطلاعاتی جهت بررسی وضعیت فعلی و آنی کاربر ارسال میشود. به همین جهت عدم کنترل میزان دسترسی به لیست اطلاعات کاربران، بار سنگینی را به بانک اطلاعاتی و CPU سیستم وارد میکند.
- هم اکنون چندین موتور جستجو و باتهایی نظر آنها در حال پیمایش سایت و برنامهی شما هستند که هر کدام از آنها میتوانند در حد یک مهاجم رفتار کنند.
به صورت خلاصه، همیشه استفادهی از برنامه، به آن نحوی که ما پیشبینی کردهایم، به پیش نمیرود و در آن لحظه، برنامه، در حال استفاده از CPU، حافظه و بانک اطلاعاتی به اشتراک گذاشته شدهی با تمام کاربران برنامهاست. در این حالت فقط یک کاربر مهاجم میتواند سبب از کار افتادن و یا به شدت کند شدن این برنامه شود و دسترسی سایر کاربران همزمان را مختل کند.
محدود کردن نرخ دسترسی به برنامه چیست؟
Rate limiting و یا نام دیگر آن request throttling، روشی است که توسط آن بتوان از الگوهای پیش بینی نشدهی استفادهی از برنامه جلوگیری کرد. عموما برنامههای وب، محدود کردن نرخ دسترسی را بر اساس تعداد بار درخواست انجام شدهی در یک بازهی زمانی مشخص، انجام میدهند و یا اگر کار برنامهی شما ارائهی فیلمهای ویدیویی است، شاید بخواهید میزان حجم استفاده شدهی توسط یک کاربر را کنترل کنید. در کل هدف نهایی از آن، کاهش و به حداقل رساندن روشهای آسیب زنندهی به برنامه و سیستم است؛ صرفنظر از اینکه این نحوهی استفادهی خاص، سهوی و یا عمدی باشد.
محدود کردن نرخ دسترسی را باید به چه منابعی اعمال کرد؟
پاسخ دقیق به این سؤال: «همه چیز» است! بله! همه چیز را کنترل کنید! در اینجا منظور از همه چیز، همان endpointهایی هستند که استفادهی نابجای از آنها میتوانند سبب کند شدن برنامه یا از دسترس خارج شدن آن شوند. برای مثال هر endpointای که از CPU، حافظه، دسترسی به دیسک سخت، بانک اطلاعاتی، APIهای ثالث و خارجی و امثال آن استفاده میکند، باید کنترل و محدود شود تا استفادهی ناصحیح یک کاربر از آنها، استفادهی از برنامه را برای سایر کاربران غیرممکن نکند. البته باید دقت داشت که هدف از اینکار، عصبی کردن کاربران عادی و معمولی برنامه نیست. هدف اصلی در اینجا، تشویق به استفادهی منصفانه از منابع سیستم است.
الگوریتمهای محدود کردن نرخ دسترسی
پیاده سازی ابتدایی محدود کردن نرخ دسترسی به منابع یک برنامه کار مشکلی است و در صورت استفاده از الگوریتمهای متداولی مانند تعریف یک جدول که شامل user-id، action-id و timestamp، به همراه یکبار ثبت اطلاعات به ازای هر درخواست و همچنین خواندن اطلاعات موجود است که جدول آن نیز به سرعت افزایش حجم میدهد. به همین جهت تعدادی الگوریتم بهینه برای اینکار طراحی شدهاند:
الگوریتمهای بازهی زمانی مشخص
در این روش، یک شمارشگر در یک بازهی زمانی مشخص فعال میشود و بر این مبنا است که محدودیتها اعمال خواهند شد. یک مثال آن، مجاز دانستن فقط «100 درخواست در یک دقیقه» است که نام دیگر آن «Quantized buckets / Fixed window limit» نیز هست.
برای مثال «نام هر اکشن + یک بازهی زمانی»، یک کلید دیکشنری نگهدارندهی اطلاعات محدود کردن نرخ دسترسی خواهد بود که به آن کلید، «bucket name» هم میگویند؛ مانند مقدار someaction_106062120. سپس به ازای هر درخواست رسیده، شمارشگر مرتبط با این کلید، یک واحد افزایش پیدا میکند و محدود کردن دسترسیها بر اساس مقدار این کلید صورت میگیرد. در ادامه با شروع هر بازهی زمانی جدید که در اینجا window نام دارد، یک کلید یا همان «bucket name» جدید تولید شده و مقدار متناظر با این کلید، به صفر تنظیم میشود.
اگر بجای دیکشنریهای #C از بانک اطلاعاتی Redis برای نگهداری این key/valueها استفاده شود، میتوان برای هر کدام از مقادیر آن، طول عمری را نیز مشخص کرد تا خود Redis، کار حذف خودکار اطلاعات غیرضروری را انجام دهد.
یک مشکل الگوریتمهای بازهی زمانی مشخص، غیر دقیق بودن آنها است. برای مثال فرض کنید که به ازای هر 10 ثانیه میخواهید تنها اجازهی پردازش 4 درخواست رسیده را بدهید. مشکل اینجا است که در این حالت یک کاربر میتواند 5 درخواست متوالی را بدون مشکل ارسال کند؛ 3 درخواست را در انتهای بازهی اول و دو درخواست را در ابتدای بازهی دوم:
به یک بازهی زمانی مشخص، fixed window و به انتها و ابتدای دو بازهی زمانی مشخص متوالی، sliding window میگویند. همانطور که در تصویر فوق هم مشاهده میکنید، در این اگوریتم، امکان محدود سازی دقیقی تنها در یک fixed window میسر است و نه در یک sliding window.
سؤال: آیا این مساله عدم دقت الگوریتمهای بازهی زمانی مشخص مهم است؟
پاسخ: بستگی دارد! اگر هدف شما، جلوگیری از استفادهی سهوی یا عمدی بیش از حد از منابع سیستم است، این مساله مشکل مهمی را ایجاد نمیکند. اما اگر دقت بالایی را انتظار دارید، بله، مهم است! در این حالت از الگوریتمهای «sliding window limit » بیشتر استفاده میشود که در پشت صحنه از همان روش استفادهی از چندین fixed window کوچک، کمک میگیرند.
الگوریتمهای سطل توکنها (Token buckets)
در دنیای مخابرات، از الگوریتمهای token buckets جهت کنترل میزان مصرف پهنای باند، زیاد استفاده میشود. از واژهی سطل در اینجا استفاده شده، چون عموما به همراه آب بکارگرفته میشود:
فرض کنید سطل آبی را دارید که در کف آن نشتی دارد. اگر نرخ پر کردن این سطل، با آب، از نرخ نشتی کف آن بیشتر باشد، آب از سطل، سرریز خواهد شد. به این معنا که با سرریز توکنها یا آب در این مثال، هیچ درخواست جدید دیگری پردازش نمیشود؛ تا زمانیکه مجددا سطل، به اندازهای خالی شود که بتواند توکن یا آب بیشتری را بپذیرد.
یکی از مزیتهای این روش، نداشتن مشکل عدم دقت به همراه بازههای زمانی مشخص است. در اینجا اگر تعداد درخواست زیادی به یکباره به سمت برنامه ارسال شوند، سطل پردازشی آنها سرریز شده و دیگر پردازش نمیشوند.
مزیت دیگر آنها، امکان بروز انفجاری یک ترافیک (bursts in traffic) نیز هست. برای مثال اگر قرار است سطلی با 60 توکن در دقیقه پر شود و این سطل نیز هر ثانیه یکبار تخلیه میشود، کلاینتها هنوز میتوانند 60 درخواست را در طی یک ثانیه ارسال کنند (ترافیک انفجاری) و پس از آن نرخ پردازشی، یک درخواست به ازای هر ثانیه خواهد شد.
آیا باید امکان بروز انفجار در ترافیک را داد؟
عموما در اکثر برنامهها وجود یک محدود کنندهی نرخ دسترسی کافی است. برای مثال یک محدود کنندهی نرخ دسترسی سراسری 600 درخواست در هر دقیقه، برای هر endpoint ای شاید مناسب باشد. اما گاهی از اوقات نیاز است تا امکان بروز انفجار در ترافیک (bursts) را نیز درنظر گرفت. برای مثال زمانیکه یک برنامهی موبایل شروع به کار میکند، در ابتدای راه اندازی آن تعداد زیادی درخواست، به سمت سرور ارسال میشوند و پس از آن، این سرعت کاهش پیدا میکند. در این حالت بهتر است چندین محدودیت را تعریف کرد: برای مثال امکان ارسال 10 درخواست در هر ثانیه و حداکثر 3600 درخواست در هر ساعت.
روش تشخیص کلاینتها چگونه باشد؟
تا اینجا در مورد bucket name یا کلید دیکشنری اطلاعات محدود کردن دسترسی به منابع، از روش «نام هر اکشن + یک بازهی زمانی» استفاده کردیم. به این کار «پارتیشن بندی درخواستها» هم گفته میشود. روشهای دیگری نیز برای انجام اینکار وجود دارند:
پارتیشن بندی به ازای هر
- endpoint
- آدرس IP. البته باید دقت داشت که کاربرانی که در پشت یک پروکسی قرار دارند، از یک IP آدرس اشتراکی استفاده میکنند.
- شماره کاربری. البته باید در اینجا بحث کاربران اعتبارسنجی نشده و anonymous را نیز مدنظر قرار داد.
- شمار سشن کاربر. در این حالت باید بحث ایجاد سشنهای جدید به ازای دستگاههای مختلف مورد استفادهی توسط کاربر را هم مدنظر قرار داد.
- نوع مروگر.
- هدر ویژه رسیده مانند X-Api-Token
بسته به نوع برنامه عموما از ترکیبی از موارد فوق برای پارتیشن بندی درخواستهای رسیده استفاده میشود.
درنظر گرفتن حالتهای استثنائی
هرچند همانطور که عنوان شد تمام قسمتهای برنامه باید از لحاظ میزان دسترسی محدود شوند، اما استثناءهای زیر را نیز باید درنظر گرفت:
- عموما تیم مدیریتی یا فروش برنامه، بیش از سایر کاربران، با برنامه کار میکنند.
- بیش از اندازه محدود کردن Web crawlers میتواند سبب کاهش امتیاز SEO سایت شما شود.
- گروههای خاصی از کاربران برنامه نیز میتوانند دسترسیهای بیشتری را خریداری کنند.
نحوهی خاتمهی اتصال و درخواست
اگر کاربری به حد نهایی استفادهی از منابع خود رسید، چه باید کرد؟ آیا باید صرفا درخواست او را برگشت زد یا اطلاعات بهتری را به او نمایش داد؟
برای مثال GitHub یک چنین خروجی را به همراه هدرهای ویژهای جهت مشخص سازی وضعیت محدود سازی دسترسی به منابع و علت آن، ارائه میدهد:
بنابراین بسته به نوع خروجی برنامه که اگر خروجی آن یک API از نوع JSON است و یا یک صفحهی HTML، میتوان از ترکیبی از هدرها و اطلاعات متنی و HTML استفاده کرد.
حتی یکسری از APIها از status codeهای ویژهای مانند 403 (دسترسی ممنوع)، 503 (سرویس در دسترس نیست) و یا 429 (تعداد درخواستهای زیاد) برای پاسخ دهی استفاده میکنند.
محل ذخیره سازی اطلاعات محدود سازی دسترسی به منابع کجا باشد؟
اگر محدودسازی دسترسی به منابع، جزئی از مدل تجاری برنامهی شما است، نیاز است حتما از یک بانک اطلاعاتی توزیع شده مانند Redis استفاده کرد تا بتواند اطلاعات تمام نمونههای در حال اجرای برنامه را پوشش دهد. اما اگر هدف از این محدود سازی تنها میسر ساختن دسترسی منصفانهی به منابع آن است، ذخیره سازی آنها در حافظهی همان نمونهی در حال اجرای برنامه هم کافی است.
چرا باید میزان دسترسی به منابع یک برنامهی وب را محدود کرد؟
فرض کنید در حال ساخت یک web API هستید که کارش ذخیره سازی لیست وظایف اشخاص است و برای مثال از یک GET /api/todos برای دریافت لیست ظایف، یک POST /api/todos برای ثبت و یک PUT /api/todos/{id} برای تغییر موارد ثبت شده، تشکیل میشود.
سؤال: چه مشکلی ممکن است به همراه این سه endpoint بروز کند؟
پاسخ: به حداقل چهار مورد زیر میتوان اشاره کرد:
- یک مهاجم سعی میکند با برنامهای که تدارک دیده، هزاران وظیفهی جدید را در چند ثانیه به سمت برنامه ارسال کند تا سبب خاتمهی سرویس آن شود.
- برنامهی ما در حین سرویس دهی، به یک سرویس ثالث نیز وابستهاست و آن سرویس ثالث، اجازهی استفادهی بیش از اندازهی از منابع خود را نمیدهد. با رسیدن تعداد زیادی درخواست به برنامهی ما تنها از طرف یک کاربر، به سقف مجاز استفادهی از آن سرویس ثالث رسیدهایم و اکنون برنامه، برای تمام کاربران آن قابل استفاده نیست.
- شخصی در حال دریافت اطلاعات تک تک کاربران است. از شماره یک شروع کرده و به همین نحو جلو میرود. برای دریافت اطلاعات کاربران، نیاز است شخص به سیستم وارد شده و اعتبارسنجی شود؛ یعنی به ازای هر درخواست، یک کوئری نیز به سمت بانک اطلاعاتی جهت بررسی وضعیت فعلی و آنی کاربر ارسال میشود. به همین جهت عدم کنترل میزان دسترسی به لیست اطلاعات کاربران، بار سنگینی را به بانک اطلاعاتی و CPU سیستم وارد میکند.
- هم اکنون چندین موتور جستجو و باتهایی نظر آنها در حال پیمایش سایت و برنامهی شما هستند که هر کدام از آنها میتوانند در حد یک مهاجم رفتار کنند.
به صورت خلاصه، همیشه استفادهی از برنامه، به آن نحوی که ما پیشبینی کردهایم، به پیش نمیرود و در آن لحظه، برنامه، در حال استفاده از CPU، حافظه و بانک اطلاعاتی به اشتراک گذاشته شدهی با تمام کاربران برنامهاست. در این حالت فقط یک کاربر مهاجم میتواند سبب از کار افتادن و یا به شدت کند شدن این برنامه شود و دسترسی سایر کاربران همزمان را مختل کند.
محدود کردن نرخ دسترسی به برنامه چیست؟
Rate limiting و یا نام دیگر آن request throttling، روشی است که توسط آن بتوان از الگوهای پیش بینی نشدهی استفادهی از برنامه جلوگیری کرد. عموما برنامههای وب، محدود کردن نرخ دسترسی را بر اساس تعداد بار درخواست انجام شدهی در یک بازهی زمانی مشخص، انجام میدهند و یا اگر کار برنامهی شما ارائهی فیلمهای ویدیویی است، شاید بخواهید میزان حجم استفاده شدهی توسط یک کاربر را کنترل کنید. در کل هدف نهایی از آن، کاهش و به حداقل رساندن روشهای آسیب زنندهی به برنامه و سیستم است؛ صرفنظر از اینکه این نحوهی استفادهی خاص، سهوی و یا عمدی باشد.
محدود کردن نرخ دسترسی را باید به چه منابعی اعمال کرد؟
پاسخ دقیق به این سؤال: «همه چیز» است! بله! همه چیز را کنترل کنید! در اینجا منظور از همه چیز، همان endpointهایی هستند که استفادهی نابجای از آنها میتوانند سبب کند شدن برنامه یا از دسترس خارج شدن آن شوند. برای مثال هر endpointای که از CPU، حافظه، دسترسی به دیسک سخت، بانک اطلاعاتی، APIهای ثالث و خارجی و امثال آن استفاده میکند، باید کنترل و محدود شود تا استفادهی ناصحیح یک کاربر از آنها، استفادهی از برنامه را برای سایر کاربران غیرممکن نکند. البته باید دقت داشت که هدف از اینکار، عصبی کردن کاربران عادی و معمولی برنامه نیست. هدف اصلی در اینجا، تشویق به استفادهی منصفانه از منابع سیستم است.
الگوریتمهای محدود کردن نرخ دسترسی
پیاده سازی ابتدایی محدود کردن نرخ دسترسی به منابع یک برنامه کار مشکلی است و در صورت استفاده از الگوریتمهای متداولی مانند تعریف یک جدول که شامل user-id، action-id و timestamp، به همراه یکبار ثبت اطلاعات به ازای هر درخواست و همچنین خواندن اطلاعات موجود است که جدول آن نیز به سرعت افزایش حجم میدهد. به همین جهت تعدادی الگوریتم بهینه برای اینکار طراحی شدهاند:
الگوریتمهای بازهی زمانی مشخص
در این روش، یک شمارشگر در یک بازهی زمانی مشخص فعال میشود و بر این مبنا است که محدودیتها اعمال خواهند شد. یک مثال آن، مجاز دانستن فقط «100 درخواست در یک دقیقه» است که نام دیگر آن «Quantized buckets / Fixed window limit» نیز هست.
برای مثال «نام هر اکشن + یک بازهی زمانی»، یک کلید دیکشنری نگهدارندهی اطلاعات محدود کردن نرخ دسترسی خواهد بود که به آن کلید، «bucket name» هم میگویند؛ مانند مقدار someaction_106062120. سپس به ازای هر درخواست رسیده، شمارشگر مرتبط با این کلید، یک واحد افزایش پیدا میکند و محدود کردن دسترسیها بر اساس مقدار این کلید صورت میگیرد. در ادامه با شروع هر بازهی زمانی جدید که در اینجا window نام دارد، یک کلید یا همان «bucket name» جدید تولید شده و مقدار متناظر با این کلید، به صفر تنظیم میشود.
اگر بجای دیکشنریهای #C از بانک اطلاعاتی Redis برای نگهداری این key/valueها استفاده شود، میتوان برای هر کدام از مقادیر آن، طول عمری را نیز مشخص کرد تا خود Redis، کار حذف خودکار اطلاعات غیرضروری را انجام دهد.
یک مشکل الگوریتمهای بازهی زمانی مشخص، غیر دقیق بودن آنها است. برای مثال فرض کنید که به ازای هر 10 ثانیه میخواهید تنها اجازهی پردازش 4 درخواست رسیده را بدهید. مشکل اینجا است که در این حالت یک کاربر میتواند 5 درخواست متوالی را بدون مشکل ارسال کند؛ 3 درخواست را در انتهای بازهی اول و دو درخواست را در ابتدای بازهی دوم:
به یک بازهی زمانی مشخص، fixed window و به انتها و ابتدای دو بازهی زمانی مشخص متوالی، sliding window میگویند. همانطور که در تصویر فوق هم مشاهده میکنید، در این اگوریتم، امکان محدود سازی دقیقی تنها در یک fixed window میسر است و نه در یک sliding window.
سؤال: آیا این مساله عدم دقت الگوریتمهای بازهی زمانی مشخص مهم است؟
پاسخ: بستگی دارد! اگر هدف شما، جلوگیری از استفادهی سهوی یا عمدی بیش از حد از منابع سیستم است، این مساله مشکل مهمی را ایجاد نمیکند. اما اگر دقت بالایی را انتظار دارید، بله، مهم است! در این حالت از الگوریتمهای «sliding window limit » بیشتر استفاده میشود که در پشت صحنه از همان روش استفادهی از چندین fixed window کوچک، کمک میگیرند.
الگوریتمهای سطل توکنها (Token buckets)
در دنیای مخابرات، از الگوریتمهای token buckets جهت کنترل میزان مصرف پهنای باند، زیاد استفاده میشود. از واژهی سطل در اینجا استفاده شده، چون عموما به همراه آب بکارگرفته میشود:
فرض کنید سطل آبی را دارید که در کف آن نشتی دارد. اگر نرخ پر کردن این سطل، با آب، از نرخ نشتی کف آن بیشتر باشد، آب از سطل، سرریز خواهد شد. به این معنا که با سرریز توکنها یا آب در این مثال، هیچ درخواست جدید دیگری پردازش نمیشود؛ تا زمانیکه مجددا سطل، به اندازهای خالی شود که بتواند توکن یا آب بیشتری را بپذیرد.
یکی از مزیتهای این روش، نداشتن مشکل عدم دقت به همراه بازههای زمانی مشخص است. در اینجا اگر تعداد درخواست زیادی به یکباره به سمت برنامه ارسال شوند، سطل پردازشی آنها سرریز شده و دیگر پردازش نمیشوند.
مزیت دیگر آنها، امکان بروز انفجاری یک ترافیک (bursts in traffic) نیز هست. برای مثال اگر قرار است سطلی با 60 توکن در دقیقه پر شود و این سطل نیز هر ثانیه یکبار تخلیه میشود، کلاینتها هنوز میتوانند 60 درخواست را در طی یک ثانیه ارسال کنند (ترافیک انفجاری) و پس از آن نرخ پردازشی، یک درخواست به ازای هر ثانیه خواهد شد.
آیا باید امکان بروز انفجار در ترافیک را داد؟
عموما در اکثر برنامهها وجود یک محدود کنندهی نرخ دسترسی کافی است. برای مثال یک محدود کنندهی نرخ دسترسی سراسری 600 درخواست در هر دقیقه، برای هر endpoint ای شاید مناسب باشد. اما گاهی از اوقات نیاز است تا امکان بروز انفجار در ترافیک (bursts) را نیز درنظر گرفت. برای مثال زمانیکه یک برنامهی موبایل شروع به کار میکند، در ابتدای راه اندازی آن تعداد زیادی درخواست، به سمت سرور ارسال میشوند و پس از آن، این سرعت کاهش پیدا میکند. در این حالت بهتر است چندین محدودیت را تعریف کرد: برای مثال امکان ارسال 10 درخواست در هر ثانیه و حداکثر 3600 درخواست در هر ساعت.
روش تشخیص کلاینتها چگونه باشد؟
تا اینجا در مورد bucket name یا کلید دیکشنری اطلاعات محدود کردن دسترسی به منابع، از روش «نام هر اکشن + یک بازهی زمانی» استفاده کردیم. به این کار «پارتیشن بندی درخواستها» هم گفته میشود. روشهای دیگری نیز برای انجام اینکار وجود دارند:
پارتیشن بندی به ازای هر
- endpoint
- آدرس IP. البته باید دقت داشت که کاربرانی که در پشت یک پروکسی قرار دارند، از یک IP آدرس اشتراکی استفاده میکنند.
- شماره کاربری. البته باید در اینجا بحث کاربران اعتبارسنجی نشده و anonymous را نیز مدنظر قرار داد.
- شمار سشن کاربر. در این حالت باید بحث ایجاد سشنهای جدید به ازای دستگاههای مختلف مورد استفادهی توسط کاربر را هم مدنظر قرار داد.
- نوع مروگر.
- هدر ویژه رسیده مانند X-Api-Token
بسته به نوع برنامه عموما از ترکیبی از موارد فوق برای پارتیشن بندی درخواستهای رسیده استفاده میشود.
درنظر گرفتن حالتهای استثنائی
هرچند همانطور که عنوان شد تمام قسمتهای برنامه باید از لحاظ میزان دسترسی محدود شوند، اما استثناءهای زیر را نیز باید درنظر گرفت:
- عموما تیم مدیریتی یا فروش برنامه، بیش از سایر کاربران، با برنامه کار میکنند.
- بیش از اندازه محدود کردن Web crawlers میتواند سبب کاهش امتیاز SEO سایت شما شود.
- گروههای خاصی از کاربران برنامه نیز میتوانند دسترسیهای بیشتری را خریداری کنند.
نحوهی خاتمهی اتصال و درخواست
اگر کاربری به حد نهایی استفادهی از منابع خود رسید، چه باید کرد؟ آیا باید صرفا درخواست او را برگشت زد یا اطلاعات بهتری را به او نمایش داد؟
برای مثال GitHub یک چنین خروجی را به همراه هدرهای ویژهای جهت مشخص سازی وضعیت محدود سازی دسترسی به منابع و علت آن، ارائه میدهد:
> HTTP/2 403 > Date: Tue, 20 Aug 2013 14:50:41 GMT > x-ratelimit-limit: 60 > x-ratelimit-remaining: 0 > x-ratelimit-used: 60 > x-ratelimit-reset: 1377013266 > { > "message": "API rate limit exceeded for xxx.xxx.xxx.xxx. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)", > "documentation_url": "https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting" > }
حتی یکسری از APIها از status codeهای ویژهای مانند 403 (دسترسی ممنوع)، 503 (سرویس در دسترس نیست) و یا 429 (تعداد درخواستهای زیاد) برای پاسخ دهی استفاده میکنند.
محل ذخیره سازی اطلاعات محدود سازی دسترسی به منابع کجا باشد؟
اگر محدودسازی دسترسی به منابع، جزئی از مدل تجاری برنامهی شما است، نیاز است حتما از یک بانک اطلاعاتی توزیع شده مانند Redis استفاده کرد تا بتواند اطلاعات تمام نمونههای در حال اجرای برنامه را پوشش دهد. اما اگر هدف از این محدود سازی تنها میسر ساختن دسترسی منصفانهی به منابع آن است، ذخیره سازی آنها در حافظهی همان نمونهی در حال اجرای برنامه هم کافی است.