پاسخ به بازخوردهای پروژهها
پاسخ به بازخوردهای پروژهها
تغییر فونت در header
بازخوردهای پروژهها
استفاده از ImageButton به جای PushButton
امکان مقداردهی ImageButton به جای PushButton در فرم طراحی شده توسط OpenOffice وجود دارد؟
مطالب
Asp.Net Identity #1
API ، Identity جدید مایکروسافت جهت مدیریت کاربران در برنامههای ASP.NET میباشد. نقطهی اتکای مایکروسافت در سالهای اخیر برای مدیریت کاربران سیستم ASP.NET Membership بود که از ضعفهای طراحی رنج میبرد. مهمترین محدودیت این سیستم این بود که دادههای ذخیره شده توسط Schema، فقط قابلیت کار با SQL Server را دارا بود که توسعهی آن بدون پیاده سازی دوبارهی کلاسهای تامین کننده ( Provider Classes ) بسیار مشکل بود. بعد از آن مایکروسافت جهت کاهش پیچیدگی سیستم ASEP.NET Membership، دو سیستم دیگر به نامهای Simple Membership و ASP.NET Universal Providers را عرضه نمود. این سیستمها تا حدودی پیچیدگی را کم کردند، اما همچنان برمبنای SQL Server بودند. تا اینکه مایکروسافت سیستم ASP.NET Membership را با سیستم Identity جهت حل دو مشکل مطرح شده تعویض نمود. سیستم Identity هم پایدار است و هم قابل توسعه. به علاوه با استفاده از قابلیت Open Source بودن، قابل وفق دادن میباشد (یعنی برحسب نیاز پروژه میتوان کل یا قسمتهایی را پیاده سازی نمود). برای بسیاری از توسعه دهندگان برنامههای ASP.NET، سیستم Identity اولین پرده برداری از OWIN خواهد بود. در حقیقت OWIN یک لایهی Abstract میباشد که برنامهی وب را از محیطی که آنرا میزبانی کرده، ایزوله میکند. هدف از ایزوله کردن، ایجاد انعطاف پذیری بیشتر در محیط هایی که برنامههای ASP.Net را میزبانی میکنند و همچنین ایجاد یک زیرساخت سبک وزن جهت سرویس دهی میباشد. همان طور که عنوان شد OWIN یک استاندارد باز است و مایکروسافت پروژه KATANA را به منظور پیاده سازی استانداردی از OWIN طراحی کرد. این طراحی همراه با یک سری کامپوننت به منظور تامین ویژگیهایی (Functionalities) که یک برنامه وب به آنها نیاز دارد همراه بود. زیبایی کار مایکروسافت در این بود که OWIN/KATANA پشتهی تکنولوژی ASP.NET را از بقیهی قسمتهای .NET Framework ایزوله کرده که اجازه نرخ بالاتری از تغییرات را میدهد.
توسعه دهندگان OWIN به جای استفاده از کل پلتفرم (بر عکس چیزی که در حال حاضر در سرویسهای ASP.NET رخ میدهد) فقط سرویسهایی را که برنامه آنها نیاز دارد، انتخاب میکنند. این سرویسهای منفرد که در واژه نامهی OWIN با نام Middleware شناخته میشوند، میتوانند در نرخهای مختلفی توسعه داده شوند و توسعه دهندگان را قادر میسازند که بین تأمین کنندگان سرویسهای مختلف یکی را انتخاب کنند و فقط وابسته به سرویسهای پیاده سازی شده توسط مایکروسافت نباشند.
و در پایان باید گفت که پلتفرم ASP.NET و IIS کنار گذاشته نخواهند شد. مایکروسافت شفاف سازی کردهاست که یکی از ابعاد زیبای OWIN این است که به توسعه دهندگان اجازه انعطاف پذیری بیشتر را میدهد که در آن کامپوننتهای Middleware بوسیله IIS میزبانی میشوند و هم اکنون پروژهی KATANA توسط فضاهای نام System.Web پشتیبانی میشود.
خوب دوستان این مقدمه ای بود بر سیستم Identity . انشالله در نوشتههای بعدی بیشتر سیستم Identity را تحلیل و بررسی خواهیم کرد.
مطالب
خواندنیهای 16 تیر
اس کیوال سرور
توسعه وب
دات نت فریم ورک
دبلیو پی اف و سیلور لایت
سی و مشتقات
شیرپوینت
کتابهای رایگان
مای اس کیوال
متفرقه
وب سرورها
پی اچ پی
وبلاگها ، سایتها و مقالات ایرانی (داخل و خارج از ایران)
- مروری بر Delphi 2009 و مهاجرت به آن
- تصحیح خودکار کلمات فارسی در برنامه اپنآفیس
- دانلود عکس از سایت
- ۱۰ قانون برای نوشتن در وب
- استفاده از SQL Server در PHP
- بلوهاست و ایران
- سورس و گزارش پروژه فارسی نت منتشر شد
- درون یک ISP چه می گذرد؟
- تابعهای جادویی PHP 5
- راهنمای کوچک همکاری در پروژههای بازمتن
- nsis قدرتمندتر از آنچه یک نصب کننده نرم افزار نیاز دارد!
- چند اشتباه رایج در طراحی وب
امنیت
Visual Studio
ASP. Net
طراحی و توسعه وب
PHP
اسکیوال سرور
سی شارپ
VB
CPP
عمومی دات نت
مسایل اجتماعی و انسانی برنامه نویسی
- چه برنامهنویسهایی را استخدام نکنید؟
- چرا خانمها کمتر در پروژههای سورس باز ظاهر میشوند؟!
- IE6 را نمیخواهیم!
متفرقه
برنامههای امروزی، ممکن است به چندین Web API مستقل، تبدیل شده و سپس برنامههایی (Front-ends) جدای از آنها برای کار با آنها ایجاد شوند. بنابراین این وظیفهی برنامههای Web API است که مطمئن شوند کلاینتها قادر به تعامل با آنها هستند. CORS استانداردی است که یک چنین امکانی را مهیا میکند.
CORS چیست؟
CORS و یا cross origin resource sharing، یک مکانیزم امنیتی است که در تمام مرورگرهای جدید جهت جلوگیری از ارسال اطلاعات یک وب سایت، به وب سایتی دیگر، درنظر گرفته شدهاست. درخواست دسترسی به یک منبع (Resource) مانند تصویر، داده و غیره، خارج از سرآغاز آن، یک درخواست cross-origin نامیده میشود. برای مدیریت یک چنین درخواستهایی، استانداردی به نام CORS طراحی شدهاست. میتوان به آن مانند نگهبانی یک ساختمان نگاه کرد که تا مجوز خاصی به آنها ارائه نشود، امکان دسترسی به منابع ساختمان را صادر نخواهند کرد.
Origin چیست؟
سرآغاز یک درخواست از سه قسمت تشکیل میشود:
- Protocol/Scheme مانند HTTP/HTTPS
- Host مانند نام دومین
- شماره پورت مانند 443 برای پروتکل HTTPS یا پورت 80 برای HTTP که عموما هر دو مورد به علت پیشفرض بودن، ذکر نمیشوند
بنابراین URLای مانند https://www.dntips.ir یک Origin را مشخص میکند. در اینجا به تمام منابعی که از این سرآغاز شروع میشوند و سه قسمت یاد شدهی آنها یکی است، same-origin گفته میشود.
در این حالت اگر منابعی به URLهایی مانند https://www.dntips.ir (پروتکل متفاوت) و یا https://github.com (با host متفاوت) اشاره کنند، به آنها Different-Origin گفته خواهد شد.
سیاست امنیتی Same-Origin چیست؟
سیاست امنیتی Same-Origin که به صورت توکار در تمام مرورگرهای امروزی تعبیه شدهاست، مانع تعامل سرآغازهایی متفاوت، جهت جلوگیری از حملات امنیتی مانند Cross-Site Request Forgery یا CSRF میشود. این سیاست امنیتی بسیار محدود کنندهاست و برای مثال مانع این میشود که بتوان توسط کدهای JavaScript ای، درخواستی را به سرآغاز دیگری ارسال کرد؛ حتی اگر بدانیم درخواست رسیده از منبعی مورد اطمینان صادر شدهاست. برای مثال اگر سایت جاری یک درخواست Ajax ای را به https://anotherwebsite.com/api/users ارسال کند، چون قسمت host مربوط به origin آنها یکی نیست، این عملیات توسط مرورگر غیرمجاز شمرده شده و مسدود میشود.
چگونه میتوان از تنظیمات CORS، برای رفع محدودیتهای سیاستهای دسترسی Same-Origin استفاده کرد؟
استاندارد CORS تعدادی header ویژه را جهت تبادل اطلاعات بین سرور و مرورگر مشخص کردهاست تا توسط آنها بتوان منابع را بین سرآغازهای متفاوتی به اشتراک گذاشت. در این حالت ابتدا کلاینت درخواستی را به سمت سرور ارسال میکند. سپس سرور پاسخی را به همراه هدرهای ویژهای که مشخص میکنند به چه منابعی و چگونه میتوان دسترسی یافت، به سمت کلاینت ارسال خواهد کرد. اکثر این هدرها با Access-Control-Allow شروع میشوند:
• Access-Control-Allow-Origin
در آن لیست سرآغازهایی را که سرور مایل است منابع خود را با آنها به اشتراک بگذارد، مشخص میشوند. در حالت توسعهی برنامه میتوان از مقدار * نیز برای آن استفاده کرد تا هر سرآغازی بتواند به منابع سرور دسترسی پیدا کند. اما از استفادهی این مقدار سراسری و کلی، در حالت انتشار برنامه خودداری کنید.
• Access-Control-Allow-Headers
• Access-Control-Allow-Methods
• Access-Control-Allow-Credentials
درخواستهای ویژهی Pre-Flight
در بسیاری از موارد، مرورگر زمانیکه تشخیص میدهد درخواست صادر شدهی از طرف برنامه، قرار است به یک Origin دیگر ارسال شود، خودش یک درخواست ویژه را به نام Pre-Flight و از نوع OPTIONS به سمت سرور ارسال میکند. علت آن این است که سرورهای قدیمی، مفهوم CORS را درک نمیکنند و در برابر درخواستهای ویژهای مانند Delete که از سرور جاری صادر نشده باشند، مقاومت میکنند (صرفا درخواستهای Same-Origin را پردازش میکنند). به همین جهت است که اگر به برگهی network ابزارهای توسعه دهندگان مرورگر خود دقت کنید، درخواستهای cross-origin به نظر دوبار ارسال شدهاند. بار اول درخواستی که method آن، options است و در خواست دوم که درخواست اصلی است و برای مثال method آن put است. این درخواست اول، Pre-Flight Request نام دارد. هدف آن این است که بررسی کند آیا سرور مقصد، استاندارد CORS را متوجه میشود یا خیر و آیا اینقدر قدیمی است که صرفا درخواستهای Same-Origin را پردازش میکند و مابقی را مسدود خواهد کرد. اگر سرور درخواست Pre-Flight را درک نکند، مرورگر درخواست اصلی را صادر نخواهد کرد.
البته درخواستهای pre-flight بیشتر در حالتهای زیر توسط مرورگر صادر میشوند:
- اگر متد اجرایی مدنظر، متدی بجز GET/POST/HEAD باشد.
- اگر content type درخواستهای از نوع POST، چیزی بجز application/x-www-form-urlencoded, multipart/form-data و یا text/plain باشند.
- اگر درخواست، به همراه یک هدر سفارشی باشد نیز سبب صدور یک pre-flight request خواهد شد.
بنابراین در برنامههای SPA خود که اطلاعات را با فرمت JSON به سمت یک Web API ارسال میکنند (و Origin آنها یکی نیست)، حتما شاهد درخواستهای Pre-Flight نیز خواهید بود.
تنظیمات CORS در ASP.NET Core
اکنون که با مفهوم CORS آشنا شدیم، در ادامه به نحوهی انجام تنظیمات آن در برنامههای ASP.NET Core خواهیم پرداخت.
تنظیمات ابتدایی CORS در فایل Startup.cs و متد ConfigureServices آن انجام میشوند:
ابتدا توسط متد AddCors، سرویسهای مرتبط، به سیستم تزریق وابستگیهای ASP.NET Core اضافه خواهند شد و سپس در قسمت تنظیمات آن میتوان همان هدرهای Access-Control-Allow را که پیشتر در مورد آنها بحث کردیم، تعریف و مقدار دهی کرد. برای مثال تنظیم AllowAnyOrigin، همان استفادهی از مقدار * در هدر Access-Control-Allow-Origin تولیدی است. باید دقت داشت که تنظیمات این سرویسها باید پیش از افزودن سرویسهای MVC انجام شوند.
در اینجا CorsPolicy که به عنوان پارامتر مشخص شدهاست، نام این سیاست دسترسی سفارشی است و در قسمتهای مختلف برنامه میتوان ارجاعاتی را به این نام تعریف کرد.
و برای تعریف سرآغازی خاص و یا متدی مشخص، میتوان به صورت زیر عمل کرد (ذکر صریح WithOrigins برای حالت توزیع برنامه مناسب است و از دیدگاه امنیتی، استفادهی از AllowAnyOrigin کار صحیحی نیست ):
پس از تنظیم سیاست دسترسی مدنظر، اکنون نوبت به اعمال آن است. اینکار در متد Configure فایل Startup.cs انجام میشود:
در اینجا متد UseCors که میانافزار CORS را فعال میکند، باید پیشاز میانافزار Mvc تعریف شود تا بتواند هدرها را اعمال کند. همچنین نامی که در اینجا به عنوان پارامتر آن استفاده شده، دقیقا به همان نامی که برای تنظیمات سیاست دسترسی درنظر گرفته شد، اشاره میکند.
متد app.UseCors، یک متد سراسری است و کل سیستم را داخل این سیاست دسترسی CORS قرار میدهد. اگر میخواهید صرفا به کنترلر خاصی این تنظیمات اعمال شوند، میتوان از فیلتر EnableCors با ذکر نام سیاست دسترسی تعریف شده، استفاده کرد (در این حالت ذکر services.AddCors ضروری است و از ذکر app.UseCors صرفنظر میشود):
و یا اگر میخواهید از app.UseCors سراسری استفاده کنید، اما آنرا برای کنترلر و یا حتی اکشن متد خاصی غیرفعال نمائید، میتوان از فیلتر [DisableCors] استفاده کرد.
چند نکته:
- به نام رشتهای سیاست دسترسی تعریف شده، دقت داشته باشید. اگر این نام را درست ذکر نکنید، هدری تولید نخواهد شد.
- میانافزار CORS، برای درخواستهای same-origin نیز هدری را تولید نمیکند.
امکان تعریف سیاستهای دسترسی بدون نام نیز وجود دارد
در هر دو روش فوق که یکی بر اساس app.UseCors سراسری و دیگری بر اساس فیلتر EnableCors اختصاصی کار میکنند، ذکر نام سیاست دسترسی options.AddPolicy ضروری است. اگر علاقهای به ذکر این نام ندارید، میتوان به طور کامل از تنظیم services.AddCors صرفنظر کرد (قسمت پارامتر و تنظیمات آنرا ذکر نکرد) و متد app.UseCors را به صورت زیر تنظیم نمود که قابلیت داشتن تنظیمات خاص خود را نیز دارا است:
روش دیگر انجام اینکار، تعریف یک DefaultPolicy است:
در اینجا در متد AddCors میتوان چندین AddPolicy نامدار را داشت، به همراه یک AddDefaultPolicy بدون نام. استفادهی از سیاست نامدار تعریف شده، یا توسط متد سراسری app.UseCors("MyCORSPolicy") انجام میشود و یا توسط فیلتر [EnableCors("MyCORSPolicy")]. اما اگر فیلتر [EnableCors] را بدون ذکر نامی قید کنیم، از همان تنظیمات AddDefaultPolicy استفاده خواهد کرد.
خطاهای متداول حین کار با CORS
خطای کار با SignalR و ارسال اطلاعات اعتبارسنجی کاربر
برای رفع این مشکل کافی است متد AllowCredentials نیز قید شود:
تمام اعتبارسنجیها و اطلاعات کوکیها در سمت سرور قابل دسترسی نیستند
CORS به صورت پیشفرض اطلاعات کوکیها را به دومینی دیگر ارسال نمیکند. در این حالت اگر حتما نیاز به انجام اینکار است، باید در درخواست Ajax ای ارسالی، خاصیت withCredentials به true تنظیم شود. همچنین سمت سرور نیز هدر Access-Control-Allow-Credentials را تنظیم کند (همان متد AllowCredentials فوق). در اینجا Credentials به کوکیها، هدرهای اعتبارسنجی (مانند هدرهای JWT) کاربران و یا مجوزهای TLS کلاینتها اشاره میکند.
CORS حساس به حروف کوچک و بزرگ است
روش دیگر تنظیم فیلتر EnableCors را در اینجا مشاهده میکنید:
اگر بجای * دقیقا origins را مشخص کردید، بخاطر داشته باشید که این تنظیم به کوچکی و بزرگی حروف حساس است و در صورت اشتباهی (مانند ذکر MyWebSite بجای mywebsite متداول با حروف کوچک)، درخواستهای رسیده مسدود خواهند شد. همچنین همانطور که ذکر شد، بین HTTP و HTTPS نیز تفاوت وجود دارد و origin اینها یکی درنظر گرفته نمیشود و حتی اگر تمام حروف را هم کوچک وارد کرده باشید، باز هم تنظیمات جداگانهای را نیاز خواهند داشت.
در حالت بروز خطای مدیریت نشدهای در سمت سرور، ASP.NET Core هدرهای CORS را ارسال نمیکند
اطلاعات بیشتر
CORS چیست؟
CORS و یا cross origin resource sharing، یک مکانیزم امنیتی است که در تمام مرورگرهای جدید جهت جلوگیری از ارسال اطلاعات یک وب سایت، به وب سایتی دیگر، درنظر گرفته شدهاست. درخواست دسترسی به یک منبع (Resource) مانند تصویر، داده و غیره، خارج از سرآغاز آن، یک درخواست cross-origin نامیده میشود. برای مدیریت یک چنین درخواستهایی، استانداردی به نام CORS طراحی شدهاست. میتوان به آن مانند نگهبانی یک ساختمان نگاه کرد که تا مجوز خاصی به آنها ارائه نشود، امکان دسترسی به منابع ساختمان را صادر نخواهند کرد.
Origin چیست؟
سرآغاز یک درخواست از سه قسمت تشکیل میشود:
- Protocol/Scheme مانند HTTP/HTTPS
- Host مانند نام دومین
- شماره پورت مانند 443 برای پروتکل HTTPS یا پورت 80 برای HTTP که عموما هر دو مورد به علت پیشفرض بودن، ذکر نمیشوند
بنابراین URLای مانند https://www.dntips.ir یک Origin را مشخص میکند. در اینجا به تمام منابعی که از این سرآغاز شروع میشوند و سه قسمت یاد شدهی آنها یکی است، same-origin گفته میشود.
در این حالت اگر منابعی به URLهایی مانند https://www.dntips.ir (پروتکل متفاوت) و یا https://github.com (با host متفاوت) اشاره کنند، به آنها Different-Origin گفته خواهد شد.
سیاست امنیتی Same-Origin چیست؟
سیاست امنیتی Same-Origin که به صورت توکار در تمام مرورگرهای امروزی تعبیه شدهاست، مانع تعامل سرآغازهایی متفاوت، جهت جلوگیری از حملات امنیتی مانند Cross-Site Request Forgery یا CSRF میشود. این سیاست امنیتی بسیار محدود کنندهاست و برای مثال مانع این میشود که بتوان توسط کدهای JavaScript ای، درخواستی را به سرآغاز دیگری ارسال کرد؛ حتی اگر بدانیم درخواست رسیده از منبعی مورد اطمینان صادر شدهاست. برای مثال اگر سایت جاری یک درخواست Ajax ای را به https://anotherwebsite.com/api/users ارسال کند، چون قسمت host مربوط به origin آنها یکی نیست، این عملیات توسط مرورگر غیرمجاز شمرده شده و مسدود میشود.
چگونه میتوان از تنظیمات CORS، برای رفع محدودیتهای سیاستهای دسترسی Same-Origin استفاده کرد؟
استاندارد CORS تعدادی header ویژه را جهت تبادل اطلاعات بین سرور و مرورگر مشخص کردهاست تا توسط آنها بتوان منابع را بین سرآغازهای متفاوتی به اشتراک گذاشت. در این حالت ابتدا کلاینت درخواستی را به سمت سرور ارسال میکند. سپس سرور پاسخی را به همراه هدرهای ویژهای که مشخص میکنند به چه منابعی و چگونه میتوان دسترسی یافت، به سمت کلاینت ارسال خواهد کرد. اکثر این هدرها با Access-Control-Allow شروع میشوند:
• Access-Control-Allow-Origin
در آن لیست سرآغازهایی را که سرور مایل است منابع خود را با آنها به اشتراک بگذارد، مشخص میشوند. در حالت توسعهی برنامه میتوان از مقدار * نیز برای آن استفاده کرد تا هر سرآغازی بتواند به منابع سرور دسترسی پیدا کند. اما از استفادهی این مقدار سراسری و کلی، در حالت انتشار برنامه خودداری کنید.
• Access-Control-Allow-Headers
• Access-Control-Allow-Methods
• Access-Control-Allow-Credentials
درخواستهای ویژهی Pre-Flight
در بسیاری از موارد، مرورگر زمانیکه تشخیص میدهد درخواست صادر شدهی از طرف برنامه، قرار است به یک Origin دیگر ارسال شود، خودش یک درخواست ویژه را به نام Pre-Flight و از نوع OPTIONS به سمت سرور ارسال میکند. علت آن این است که سرورهای قدیمی، مفهوم CORS را درک نمیکنند و در برابر درخواستهای ویژهای مانند Delete که از سرور جاری صادر نشده باشند، مقاومت میکنند (صرفا درخواستهای Same-Origin را پردازش میکنند). به همین جهت است که اگر به برگهی network ابزارهای توسعه دهندگان مرورگر خود دقت کنید، درخواستهای cross-origin به نظر دوبار ارسال شدهاند. بار اول درخواستی که method آن، options است و در خواست دوم که درخواست اصلی است و برای مثال method آن put است. این درخواست اول، Pre-Flight Request نام دارد. هدف آن این است که بررسی کند آیا سرور مقصد، استاندارد CORS را متوجه میشود یا خیر و آیا اینقدر قدیمی است که صرفا درخواستهای Same-Origin را پردازش میکند و مابقی را مسدود خواهد کرد. اگر سرور درخواست Pre-Flight را درک نکند، مرورگر درخواست اصلی را صادر نخواهد کرد.
البته درخواستهای pre-flight بیشتر در حالتهای زیر توسط مرورگر صادر میشوند:
- اگر متد اجرایی مدنظر، متدی بجز GET/POST/HEAD باشد.
- اگر content type درخواستهای از نوع POST، چیزی بجز application/x-www-form-urlencoded, multipart/form-data و یا text/plain باشند.
- اگر درخواست، به همراه یک هدر سفارشی باشد نیز سبب صدور یک pre-flight request خواهد شد.
بنابراین در برنامههای SPA خود که اطلاعات را با فرمت JSON به سمت یک Web API ارسال میکنند (و Origin آنها یکی نیست)، حتما شاهد درخواستهای Pre-Flight نیز خواهید بود.
تنظیمات CORS در ASP.NET Core
اکنون که با مفهوم CORS آشنا شدیم، در ادامه به نحوهی انجام تنظیمات آن در برنامههای ASP.NET Core خواهیم پرداخت.
تنظیمات ابتدایی CORS در فایل Startup.cs و متد ConfigureServices آن انجام میشوند:
public void ConfigureServices(IServiceCollection services) { // Add service and create Policy with options services.AddCors(options => { options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials() ); }); // Make sure MVC is added AFTER CORS services.AddMvc(); }
در اینجا CorsPolicy که به عنوان پارامتر مشخص شدهاست، نام این سیاست دسترسی سفارشی است و در قسمتهای مختلف برنامه میتوان ارجاعاتی را به این نام تعریف کرد.
و برای تعریف سرآغازی خاص و یا متدی مشخص، میتوان به صورت زیر عمل کرد (ذکر صریح WithOrigins برای حالت توزیع برنامه مناسب است و از دیدگاه امنیتی، استفادهی از AllowAnyOrigin کار صحیحی نیست ):
services.AddCors(options => { options.AddPolicy("AllowOrigin", builder => builder.WithOrigins("http://localhost:55294") .WithMethods("GET", "POST", "HEAD")); });
پس از تنظیم سیاست دسترسی مدنظر، اکنون نوبت به اعمال آن است. اینکار در متد Configure فایل Startup.cs انجام میشود:
public void Configure(IApplicationBuilder app) { // ... app.UseCors("CorsPolicy"); // ... app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
متد app.UseCors، یک متد سراسری است و کل سیستم را داخل این سیاست دسترسی CORS قرار میدهد. اگر میخواهید صرفا به کنترلر خاصی این تنظیمات اعمال شوند، میتوان از فیلتر EnableCors با ذکر نام سیاست دسترسی تعریف شده، استفاده کرد (در این حالت ذکر services.AddCors ضروری است و از ذکر app.UseCors صرفنظر میشود):
[EnableCors("CorsPolicy")] public class MyApiController : Controller
و یا اگر میخواهید از app.UseCors سراسری استفاده کنید، اما آنرا برای کنترلر و یا حتی اکشن متد خاصی غیرفعال نمائید، میتوان از فیلتر [DisableCors] استفاده کرد.
چند نکته:
- به نام رشتهای سیاست دسترسی تعریف شده، دقت داشته باشید. اگر این نام را درست ذکر نکنید، هدری تولید نخواهد شد.
- میانافزار CORS، برای درخواستهای same-origin نیز هدری را تولید نمیکند.
امکان تعریف سیاستهای دسترسی بدون نام نیز وجود دارد
در هر دو روش فوق که یکی بر اساس app.UseCors سراسری و دیگری بر اساس فیلتر EnableCors اختصاصی کار میکنند، ذکر نام سیاست دسترسی options.AddPolicy ضروری است. اگر علاقهای به ذکر این نام ندارید، میتوان به طور کامل از تنظیم services.AddCors صرفنظر کرد (قسمت پارامتر و تنظیمات آنرا ذکر نکرد) و متد app.UseCors را به صورت زیر تنظیم نمود که قابلیت داشتن تنظیمات خاص خود را نیز دارا است:
public void ConfigureServices(IServiceCollection services) { services.AddCors(); services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseCors(policyBuilder => { string[] origins = new string[] { "http://localhost:2000", "http://localhost:2001" }; policyBuilder .AllowAnyHeader() .AllowAnyMethod() .WithOrigins(origins); }); app.UseMvc(); }
روش دیگر انجام اینکار، تعریف یک DefaultPolicy است:
public void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddDefaultPolicy( builder => { builder .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); options.AddPolicy("MyCORSPolicy", builder => { builder.WithOrigins("http://localhost:49373") .AllowAnyHeader() .AllowAnyMethod(); }); }); services.AddMvc().AddNewtonsoftJson(); }
خطاهای متداول حین کار با CORS
خطای کار با SignalR و ارسال اطلاعات اعتبارسنجی کاربر
Access to XMLHttpRequest at 'http://localhost:22135/chat/negotiate?jwt=<removed the jwt key>' from origin 'http://localhost:53150' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
services.AddCors(options => { options.AddPolicy("AllowAllOrigins", builder => { builder .AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); });
تمام اعتبارسنجیها و اطلاعات کوکیها در سمت سرور قابل دسترسی نیستند
CORS به صورت پیشفرض اطلاعات کوکیها را به دومینی دیگر ارسال نمیکند. در این حالت اگر حتما نیاز به انجام اینکار است، باید در درخواست Ajax ای ارسالی، خاصیت withCredentials به true تنظیم شود. همچنین سمت سرور نیز هدر Access-Control-Allow-Credentials را تنظیم کند (همان متد AllowCredentials فوق). در اینجا Credentials به کوکیها، هدرهای اعتبارسنجی (مانند هدرهای JWT) کاربران و یا مجوزهای TLS کلاینتها اشاره میکند.
var xhr = new XMLHttpRequest(); xhr.open('get', 'http://www.example.com/api/test'); xhr.withCredentials = true; //In jQuery: $.ajax({ type: 'get', url: 'http://www.example.com/home', xhrFields: { withCredentials: true } //ES6 fetch API: fetch( 'http://remote-url.com/users', { 'PUT', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, mode: 'cors', credentials: 'include', body: JSON.stringify(body) } ) .then((response) => response.json()) .then((response) => console.log(response)) .catch((error) => console.error(error));
CORS حساس به حروف کوچک و بزرگ است
روش دیگر تنظیم فیلتر EnableCors را در اینجا مشاهده میکنید:
[EnableCors(origins: "http://MyWebsite.com", headers: "*", methods: "*")] //is not the same as this: [EnableCors(origins:"http://mywebsite.com", headers: "*", methods: "*")]
در حالت بروز خطای مدیریت نشدهای در سمت سرور، ASP.NET Core هدرهای CORS را ارسال نمیکند
اطلاعات بیشتر
نظرات مطالب
Owin چیست ؟ قسمت اول
بله، به همین معنی است
البته دقت کنید، پیاده سازی OWIN کار ساده ای نیست، و به سرعت نمیتوان شاهد پیاده سازی آن بر روی هاستهای مختلف بود، و این پروسه با سرعت فعلی از نظر من مدتی طول خواهد کشید.
برای مثال Katana که یک پیاده سازی قابل استفاده و خوب از آن به شمار میرود کار شرکت مایکروسافت است و سایر پیاده سازی Open Source سایر تیمها که بالطبع امکان مانور شرکت مایکروسافت را ندارند، کمی طول میکشد تا واقعا آماده استفاده شود.
و همچنین پیاده سازیهای فعلی در قسمت هایی مانند Web Socketها و سایر مسائل پیچیده دارای ضعف هایی هستند.
درست مانند استاندارد HTML 5 که بر روی مرورگرهای مختلف به میزانهای مختلفی پیاده سازی شده است.
به بیان دیگر پیاده سازی OWIN صفر و صدی نیست، بلکه هر پیاده سازی ممکن است در داخل خود دارای ضعفها و یا نواقصی باشد.
علاوه بر این اگر شما در کد نویسی ASP.NET MVC خود، بی جهت به امکانات پایه ASP.NET ایجاد وابستگی کنید، نیز در این عمل دچار مشکل خواهید شد، برای همین بدیهتا کاری را که میتوانید با Action Filter انجام دهید را نباید با یک Http Module انجام دهید و ...
مهمترین کار طراحی برنامه هایی که مینویسید به صورت سازگار با OWIN است که در پستهای بعدی قرار است به همین قسم از مطالب بپردازیم
البته من آینده خوبی برای OWIN قائلم، و نفع آن در کوتاه مدت و بلند مدت کاملا آشکار و واضح است، کما این که در مطلب به آن اشاره شد.
برای مشاهده پیاده سازیهای مختلف OWIN میتوانید به سایت owin.org مراجعه کنید.
موفق و پایدار باشید
احتمالا به اهمیت بحث SEO و آدرسهای تمیز آن آشنا هستید. ASP.NET MVC از همان ابتدا از قابلیت URL Routing پشتیبانی میکرد و ASP.NET Web Forms هم از نسخه NET 4.0. این قابلیت را در خود اضافه نمود. با این حال نوشتن Url Routing برای وب سایتها کمی مشکل و در ASP.NET کمتر استفاده میشود. علاوه بر آن تغییر آدرسهای قدیمی با Url Routing بسیار وقت گیر میباشد. به همین خاطر تیم توسعه ASP.NET کتابخانه ای با نام Asp.NET FriendlyUrls که فعلا نسخه قبل از نهایی آن منتشر شده است را در اختیار توسعه دهندگان وب سایتها قرار دادهاند که با حداقل کد نویسی و بدون اضافه نمودن مسیریابی آدرسها، تمام آدرسهای قدیم و جدید را مطابق استاندارد SEO تغییر میدهد.
در آخر، فضای نام کتابخانه، Microsoft.AspNet.FriendlyUrls میباشد.
دریافت و نصب Asp.NET FriendlyUrls از Nuget
در Visual Studio 2012.2 در صورتی که یک پروژه جدید از نوع ASP.NET Web Forms ایجاد نمایید بصورت پیشفرض این کتابخانه نصب شده است. اما میتوانید با دستور زیر نیز آن را از Nuget دریافت نمایید:
Install-Package Microsoft.AspNet.FriendlyUrls -Pre
پس از نصب، در کلاس Global میبایست کتابخانه را فعال نمایید:
public static class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.EnableFriendlyUrls(); } }
و همچنین در Application_Start
void Application_Start(object sender, EventArgs e) { RouteConfig.RegisterRoutes(RouteTable.Routes); }
به همین راحتی؛ حال دو صفحه First.aspx و Second.aspx را به پروژه اضافه نمائید و وب سایت را اجرا کنید. بدون نوشتن پسوند aspx به صفحات دسترسی خواهید داشت:
از درون برنامه هم به راحتی میتوانید صفحات را به همان صورت قبل بدون پسوند صدا بزنید:
Response.Redirect("~\\Second");
دسترسی به پارامترها نیز به صورت قبل امکان پذیر میباشد:
Response.Redirect("~\\First?Id=1001"); string Id = Request.QueryString["Id"] as string;
برای آدرسهای پیشرفتهتر، 3 متود الحاقی اضافه گردیده است. مثلا اگر آدرس زیر را داشته باشیم
http://localhost:57353/First/Products/NewProduct
- ()Request.GetFriendlyUrlFileVirtualPath
مسیر مجازی فایل را بر میگرداند - ()Request.GetFriendlyUrlSegments
بخشهای آدرس را بر میگرداند - ()Request.GetFriendlyUrlFileExtension
پسوند فایل آدرس را بر میگرداند
کلاس FriendlyUrl دو متود استاتیک و یک خاصیت دارد
- FriendlyUrl.Segments
شبیه ()Request.GetFriendlyUrlSegments مجموعه بخشهای آدرس صفحه جاری را بر میگرداند - FriendlyUrl.Resolve
آدرس صفحه جاری را بر میگرداند - FriendlyUrl.Href
امکان ساخت یک آدرس را با استفاده از مسیر مجازی، بخشها و پارامترها، فراهم مینماید
در آخر، فضای نام کتابخانه، Microsoft.AspNet.FriendlyUrls میباشد.
نظرات اشتراکها
StructureMap 3.0 منتشر شد
سلام؛ اگه ممکنه در مورد نحوه تنظیم استراکچرمپ و web api راهنمایی کنید.