مطالب
امن سازی برنامه‌های ASP.NET Core توسط IdentityServer 4x - قسمت چهارم - نصب و راه اندازی IdentityServer
معرفی IdentityServer 4


اگر استاندارد OpenID Connect را بررسی کنیم، از مجموعه‌ای از دستورات و رهنمودها تشکیل شده‌است. بنابراین نیاز به کامپوننتی داریم که این استاندارد را پیاده سازی کرده باشد تا بتوان بر اساس آن یک Identity Provider را تشکیل داد و پیاده سازی مباحثی که در قسمت قبل بررسی شدند مانند توکن‌ها، Flow، انواع کلاینت‌ها، انواع Endpoints و غیره چیزی نیستند که به سادگی قابل انجام باشند. اینجا است که IdentityServer 4، به عنوان یک فریم ورک پیاده سازی کننده‌ی استانداردهای OAuth 2 و OpenID Connect مخصوص ASP.NET Core ارائه شده‌است. این فریم ورک توسط OpenID Foundation تائید شده و داری مجوز رسمی از آن است. همچنین جزئی از NET Foundation. نیز می‌باشد. به علاوه باید دقت داشت که این فریم ورک کاملا سورس باز است.


نصب و راه اندازی IdentityServer 4

همان مثال «قسمت دوم - ایجاد ساختار اولیه‌ی مثال این سری» را در نظر بگیرید. داخل آن پوشه‌های جدید src\IDP\DNT.IDP را ایجاد می‌کنیم.


نام دلخواه DNT.IDP، به پوشه‌ی جدیدی اشاره می‌کند که قصد داریم IDP خود را در آن برپا کنیم. نام آن را نیز در ادامه‌ی نام‌های پروژه‌های قبلی که با ImageGallery شروع شده‌اند نیز انتخاب نکرده‌ایم؛ از این جهت که یک IDP را قرار است برای بیش از یک برنامه‌ی کلاینت مورد استفاده قرار دهیم. برای مثال می‌توانید از نام شرکت خود برای نامگذاری این IDP استفاده کنید.

اکنون از طریق خط فرمان به پوشه‌ی src\IDP\DNT.IDP وارد شده و دستور زیر را صادر کنید:
dotnet new web
این دستور، یک پروژه‌ی جدیدی را از نوع «ASP.NET Core Empty»، در این پوشه، بر اساس آخرین نگارش SDK نصب شده‌ی بر روی سیستم شما، ایجاد می‌کند. از این جهت نوع پروژه خالی درنظر گرفته شده‌است که قرار است توسط اجزای IdentityServer 4 به مرور تکمیل شود.

اولین کاری را که در اینجا انجام خواهیم داد، مراجعه به فایل Properties\launchSettings.json آن و تغییر شماره پورت‌های پیش‌فرض آن است تا با سایر پروژه‌های وبی که تاکنون ایجاد کرده‌ایم، تداخل نکند. برای مثال در اینجا شماره پورت SSL آن‌را به 6001 تغییر داده‌ایم.

اکنون نوبت به افزودن میان‌افزار IdentityServer 4 به پروژه‌ی خالی وب است. اینکار را نیز توسط اجرای دستور زیر در پوشه‌ی src\IDP\DNT.IDP انجام می‌دهیم:
 dotnet add package IdentityServer4

در ادامه نیاز است این میان‌افزار جدید را معرفی و تنظیم کرد. به همین جهت فایل Startup.cs پروژه‌ی خالی وب را گشوده و به صورت زیر تکمیل می‌کنیم:
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            services.AddIdentityServer()
                .AddDeveloperSigningCredential();
        }
- متد الحاقی AddIdentityServer، کار ثبت و معرفی سرویس‌های توکار IdentityServer را به سرویس توکار تزریق وابستگی‌های ASP.NET Core انجام می‌دهد.
- متد الحاقی AddDeveloperSigningCredential کار تنظیمات کلید امضای دیجیتال توکن‌ها را انجام می‌دهد. در نگارش‌های قبلی IdentityServer، اینکار با معرفی یک مجوز امضاء کردن توکن‌ها انجام می‌شد. اما در این نگارش دیگر نیازی به آن نیست. در طول توسعه‌ی برنامه می‌توان از نگارش Developer این مجوز استفاده کرد. البته در حین توزیع برنامه به محیط ارائه‌ی نهایی، باید به یک مجوز واقعی تغییر پیدا کند.


تعریف کاربران، منابع و کلاینت‌ها

مرحله‌ی بعدی تنظیمات میان‌افزار IdentityServer4، تعریف کاربران، منابع و کلاینت‌های این IDP است. به همین جهت یک کلاس جدید را به نام Config، در ریشه‌ی پروژه ایجاد و به صورت زیر تکمیل می‌کنیم:
using System.Collections.Generic;
using System.Security.Claims;
using IdentityServer4.Models;
using IdentityServer4.Test;

namespace DNT.IDP
{
    public static class Config
    {
        // test users
        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>
            {
                new TestUser
                {
                    SubjectId = "d860efca-22d9-47fd-8249-791ba61b07c7",
                    Username = "User 1",
                    Password = "password",

                    Claims = new List<Claim>
                    {
                        new Claim("given_name", "Vahid"),
                        new Claim("family_name", "N"),
                    }
                },
                new TestUser
                {
                    SubjectId = "b7539694-97e7-4dfe-84da-b4256e1ff5c7",
                    Username = "User 2",
                    Password = "password",

                    Claims = new List<Claim>
                    {
                        new Claim("given_name", "User 2"),
                        new Claim("family_name", "Test"),
                    }
                }
            };
        }

        // identity-related resources (scopes)
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile()
            };
        }

        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>();
        }
    }
}
توضیحات:
- این کلاس استاتیک، اطلاعاتی درون حافظه‌ای را برای تکمیل دموی جاری ارائه می‌دهد.

- ابتدا در متد GetUsers، تعدادی کاربر آزمایشی اضافه شده‌اند. کلاس TestUser در فضای نام IdentityServer4.Test قرار دارد. در کلاس TestUser، خاصیت SubjectId، بیانگر Id منحصربفرد هر کاربر در کل این IDP است. سپس نام کاربری، کلمه‌ی عبور و تعدادی Claim برای هر کاربر تعریف شده‌اند که بیانگر اطلاعاتی اضافی در مورد هر کدام از آن‌ها هستند. برای مثال نام و نام خانوادگی جزو خواص کلاس TestUser نیستند؛ اما منعی هم برای تعریف آن‌ها وجود ندارد. اینگونه اطلاعات اضافی را می‌توان توسط Claims به سیستم اضافه کرد.

- بازگشت Claims توسط یک IDP مرتبط است به مفهوم Scopes. برای این منظور متد دیگری به نام GetIdentityResources تعریف شده‌است تا لیستی از IdentityResource‌ها را بازگشت دهد که در فضای نام IdentityServer4.Models قرار دارد. هر IdentityResource، به یک Scope که سبب دسترسی به اطلاعات Identity کاربران می‌شود، نگاشت خواهد شد. در اینجا چون از پروتکل OpenID Connect استفاده می‌کنیم، ذکر IdentityResources.OpenId اجباری است. به این ترتیب مطمئن خواهیم شد که SubjectId به سمت برنامه‌ی کلاینت بازگشت داده می‌شود. برای بازگشت Claims نیز باید IdentityResources.Profile را به عنوان یک Scope دیگری مشخص کرد که در متد GetIdentityResources مشخص شده‌است.

- در آخر نیاز است کلاینت‌های این IDP را نیز مشخص کنیم (در مورد مفهوم Clients در قسمت قبل بیشتر توضیح داده شد) که اینکار در متد GetClients انجام می‌شود. فعلا یک لیست خالی را بازگشت می‌دهیم و آن‌را در قسمت‌های بعدی تکمیل خواهیم کرد.


افزودن کاربران، منابع و کلاینت‌ها به سیستم

پس از تعریف و تکمیل کلاس Config، برای معرفی آن به IDP، به کلاس آغازین برنامه مراجعه کرده و آن‌را به صورت زیر تکمیل می‌کنیم:
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            services.AddIdentityServer()
             .AddDeveloperSigningCredential()
             .AddTestUsers(Config.GetUsers())
             .AddInMemoryIdentityResources(Config.GetIdentityResources())
             .AddInMemoryClients(Config.GetClients());
        }
در اینجا لیست کاربران و اطلاعات آن‌ها توسط متد AddTestUsers، لیست منابع و Scopes توسط متد AddInMemoryIdentityResources و لیست کلاینت‌ها توسط متد AddInMemoryClients به تنظیمات IdentityServer اضافه شده‌اند.


افزودن میان افزار IdentityServer به برنامه

پس از انجام تنظیمات مقدماتی سرویس‌های برنامه، اکنون نوبت به افزودن میان‌افزار IdentityServer است که در کلاس آغازین برنامه به صورت زیر تعریف می‌شود:
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseIdentityServer();
            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }

آزمایش IDP

اکنون برای آزمایش IDP، به پوشه‌ی src\IDP\DNT.IDP وارد شده و دستور dotnet run را اجرا کنید:


همانطور که ملاحظه می‌کنید، برنامه‌ی IDP بر روی پورت 6001 قابل دسترسی است. برای آزمایش Web API آن، آدرس discovery endpoint این IDP را به صورت زیر در مرورگر وارد کنید:
 https://localhost:6001/.well-known/openid-configuration


در این تصویر، مفاهیمی را که در قسمت قبل بررسی کردیم مانند authorization_endpoint ،token_endpoint و غیره، مشاهده می‌کنید.


افزودن UI به IdentityServer

تا اینجا میان‌افزار IdentityServer را نصب و راه اندازی کردیم. در نگارش‌های قبلی آن، UI به صورت پیش‌فرض جزئی از این سیستم بود. در این نگارش آن‌را می‌توان به صورت جداگانه دریافت و به برنامه اضافه کرد. برای این منظور به آدرس IdentityServer4.Quickstart.UI مراجعه کرده و همانطور که در readme آن ذکر شده‌است می‌توان از یکی از دستورات زیر برای افزودن آن به پروژه‌ی IDP استفاده کرد:
الف) در ویندوز از طریق کنسول پاورشل به پوشه‌ی src\IDP\DNT.IDP وارد شده و سپس دستور زیر را وارد کنید:
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.ps1'))
ب) و یا درmacOS و یا Linux، دستور زیر را اجرا کنید:
\curl -L https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.sh | bash

یک نکته: در ویندوز اگر در نوار آدرس هر پوشه، عبارت cmd را وارد و enter کنید، کنسول خط فرمان ویندوز در همان پوشه باز خواهد شد. همچنین در اینجا از ورود عبارت powershell هم پشتیبانی می‌شود:


بنابراین در نوار آدرس پوشه‌ی src\IDP\DNT.IDP، عبارت powershell را وارد کرده و سپس enter کنید. پس از آن دستور الف را وارد (copy/paste) و اجرا کنید.


به این ترتیب فایل‌های IdentityServer4.Quickstart.UI به پروژه‌ی IDP جاری اضافه می‌شوند.
- پس از آن اگر به پوشه‌ی Views مراجعه کنید، برای نمونه ذیل پوشه‌ی Account آن، Viewهای ورود و خروج به سیستم قابل مشاهده هستند.
- در پوشه‌ی Quickstart آن، کدهای کامل کنترلرهای متناظر با این Viewها قرار دارند.
بنابراین اگر نیاز به سفارشی سازی این Viewها را داشته باشید، کدهای کامل کنترلرها و Viewهای آن هم اکنون در پروژه‌ی IDP جاری در دسترس هستند.

نکته‌ی مهم: این UI اضافه شده، یک برنامه‌ی ASP.NET Core MVC است. به همین جهت در انتهای متد Configure، ذکر میان افزارهای UseStaticFiles و همچنین UseMvcWithDefaultRoute انجام شدند.

اکنون اگر برنامه‌ی IDP را مجددا با دستور dotnet run اجرا کنیم، تصویر زیر را می‌توان در ریشه‌ی سایت، مشاهده کرد که برای مثال لینک discovery endpoint در همان سطر اول آن ذکر شده‌است:


همچنین همانطور که در قسمت قبل نیز ذکر شد، یک IDP حتما باید از طریق پروتکل HTTPS در دسترس قرار گیرد که در پروژه‌های ASP.NET Core 2.1 این حالت، جزو تنظیمات پیش‌فرض است.


کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید.
اشتراک‌ها
API نویسی اصولی و حرفه ای در ASP.NET Core

Professional REST API design with ASP.NET Core and WebAPI

This project is an example of lightweight and extensible infrastructure for building RESTful Web API with ASP.NET Core.

This example contains a number of tricks and techniques which I've learned while building APIs in ASP.NET Core.

Techniques and Features

  •  JWT Authentication
  • Secure JWT using Encryption (JWE)
  • Logging to File, Console and Database using Elmah & NLog
  • Logging to sentry.io (Log Management System)
  • Exception Handling using Custom Middleware
  • Automatic Validation
  • Standard API Resulting
  • Dependency Injection using Autofac
  • Map resources using AutoMapper
  • Async/Await Best Practices
  • Versioning Management
  • Using Swagger (Swashbuckle)
  • Auto Document Generator for Swagger
  • Integrate Swagger and Versioning
  • Integrate Swagger and JWT/OAuth Authentication
  • Best Practices for Performance and Security 
API نویسی اصولی و حرفه ای در ASP.NET Core
نظرات مطالب
Blazor 5x - قسمت 34 - توزیع برنامه‌های Blazor بر روی IIS
نمونه‌ای از راه اندازی یک برنامه‌ی Blazor WASM در IIS

الف) به قسمت application pools در IIS Manager مراجعه کرده و گزینه‌ی add application pool را انتخاب کنید. سپس یک نمونه‌ی جدید را برای مثال به نام no-managed ایجاد کنید که net clr version. آن به گزینه‌ی no managed code اشاره می‌کند.
ب) پس از publish برنامه مطابق مطلب فوق (برای مثال با اجرای دستور dotnet publish -c Release) و معرفی مسیر پوشه‌ی publish به IIS (برای مثال به عنوان یک Application جدید ذیل default web site با کلیک راست بر روی default web site و انتخاب گزینه‌ی Add application)، این application pool جدید را به برنامه‌ی خود در IIS نسبت دهید. برای اینکار basic settings سایت را باز کرده و بر روی دکمه‌ی select که در کنار نام application pool هست، کلیک کرده و گزینه‌ی no-managed قسمت الف را انتخاب کنید.

نکته 1: برنامه‌های blazor wasm، یا standalone هستند و یا hosted. مورد standalone یعنی کاری به Web API ندارد و به خودی خود، به صورت یک سایت استاتیک قابل مشاهده‌است. حالت hosted یعنی به همراه web api هم هست و توسط دستور برای مثال «dotnet new blazorwasm -o BlazorIIS --hosted --no-https» ایجاد می‌شود که به همراه سه پوشه‌ی کلاینت، سرور و shared است. برای توزیع حالت متکی به خود، فقط محتویات پوشه‌ی publish، به عنوان مسیر برنامه، در IIS معرفی خواهند شد. در حالت hosted، مسیر اصلی، پوشه‌ی publish مربوط به پروژه‌ی سرور است؛ یعنی: Server\bin\Release\net5.0\publish. در این حالت پوشه‌ی Client\bin\Release\net5.0\publish باید به داخل همین پوشه‌ی publish سرور کپی شود. یعنی پوشه‌ی publish پروژه‌ی client باید به درون پوشه‌ی publish پروژه‌ی server کپی شود تا با هم یک برنامه‌ی قابل توزیع توسط IIS را تشکیل دهند.
در اینجا تنها فایل‌هایی که تداخل پیدا می‌کنند، فایل‌های web.config هستند که باید یکی شوند. فایل web.config برنامه‌ی web api با برنامه‌ی client یکی نیست، اما می‌توان محتویات این دو را با هم یکی کرد.
نکته 2: محل اجرای دستور dotnet publish -c Release مهم است. اگر این دستور را در کنار فایل sln پروژه‌ی hosted اجرا کنید، سه خروجی نهایی publish را تولید می‌کند و پس از آن باید فایل‌های کلاینت را به سرور، به صورت دستی کپی کرد. اما اگر دستور publish را درون پوشه‌ی سرور اجرا کنید، کار کپی فایل‌های کلاینت را به درون پوشه‌ی نهایی publish تشکیل شده، به صورت خودکار انجام می‌دهد؛ علت اینجا است که اگر به فایل csproj. پروژه‌ی سرور دقت کنید، ارجاعی را به پروژه‌ی کلاینت نیز دارد (هر چند ما از کدهای آن در برنامه‌ی web api استفاده نمی‌کنیم). این ارجاع تنها کمک حال دستور dotnet publish -c Release است و کاربرد دیگری را ندارد.

ج) اکنون اگر برنامه را برای مثال با مسیر فرضی جدید http://localhost/blazortest اجرا کنید، خطای 500.19 را دریافت می‌کنید. علت آن‌را در مطلب «بررسی خطاهای ممکن در حین راه اندازی اولیه برنامه‌های ASP.NET Core در IIS» بررسی کرده‌ایم. باید IIS URL Rewrite ماژول را نصب کرد؛ تا این مشکل برطرف شود. همچنین دلیل دیگر مشاهده‌ی این خطا، عدم نصب بسته‌ی هاستینگ متناظر با شماره نگارش NET. مورد استفاده‌است (اگر برنامه‌ی شما از نوع hosted است و web api هم دارد).
د) پس از آن باز هم برنامه اجرا نمی‌شود! اگر در خطاها دقت کنید، به دنبال اسکریپت‌هایی شروع شده از مسیر localhost است و نه از پوشه‌ی جدید blazortest. برای رفع این مشکل باید فایل publish\wwwroot\index.html را مطابق نکته‌ی base-URL که کمی بالاتر ذکر شد، ویرایش کرد تا blazor بداند که فایل‌ها، در چه مسیری قرار دارند (و در ریشه‌ی سایت واقع نشده‌اند):
<head>
<base href="/blazortest/" />
اکنون برنامه بدون مشکل بارگذاری و اجرا می‌شود.
مطالب
کتابچه‌ی رایگان نصب و راه اندازی Exchange Server 2010

در طی این چند سالی که کارم برنامه نویسی ASP.Net بوده است، هیچ نرم افزار پایه‌ای همانند Exchange server در کیفیت کارهای من تاثیر نداشته است و اساسا تمام هماهنگی‌های برنامه‌های من با کمک Exchange server و Outlook صورت می‌گیرد. از گرفتن تائید تا آلارم فلان درخواست تا یک سری از گزارشات زمانبندی شده و غیره. دیگر کار به جایی رسیده است که اگر کاربران ایمیلی را دریافت نکنند اطلاعات وارد شده در برنامه‌ها را معتبر نمی‌دانند و به برنامه‌ها مراجعه نمی‌کنند!
به همین منظور کتابچه‌ی راهنمای نصب و راه اندازی Exchange server 2010 را تهیه کرده‌ام که در طی حدودا 120 صفحه، به صورت کاربردی و ساده، آنچه را که باید برای راه اندازی و مدیریت این برنامه در یک سازمان بدانید، در اختیار شما قرار می‌دهد.

مقدمه‌ی کتابچه

برنامه‌ی Exchanger server ، نرم افزار ارسال و دریافت ایمیل سازمانی مایکروسافت است که در رده‌ی محصولات سرور آن شرکت قرار می‌گیرد. اولین نگارش Exchanger server در سال 1993 ارائه شد و به صورت محدود در اختیار حدود 500 شرکت قرار گرفت. در سال 1996 اولین نگارش عمومی آن به نام Exchange server 4.0 به عموم ارائه گشت و در سال 1997 با ارائه‌ی Exchange server 5.0 آمار مشتریان این محصول به 32 هزار کاربر رسید. به همراه این نگارش، اولین نسخه‌ی برنامه Outlook web access نیز ارائه گردید. با افزایش استقبال از این محصول، در همان سال نگارش 5.5 آن نیز ارائه شد و ظرفیت بانک‌های اطلاعاتی آن تا 16TB در نگارش سازمانی آن افزایش یافت. در سال 2000، اولین نگارش یکپارچه‌ی آن با Active directory ارائه شد. بزرگترین مشکل این محصول در سال 2000، کوچ از نگارش‌های قدیمی به نگارش جدید بودند که این مشکل در سال 2003 با ارائه Exchange server 2003 برطرف گردید. در اواخر سال 2006 ، Exchange server 2007 ارائه گشت که مهمترین تفاوت آن با نگارش‌های قبلی، ارائه‌ی آن تنها برای سکوهای 64 بیتی بود به همراه بهبودهایی در اندازه‌ی صندوق‌های پستی تا 2 گیگابایت، تضمین فعالیت بی‌وقفه بهبود یافته ، شروع به کنار گذاری Public folders و تمهیداتی جهت ارسال و دریافت پیغام‌های صوتی. در اواخر سال 2009 نگارش 2010 این محصول ارائه گشت که تنها با ویندوز سرور 2008 سازگار می‌باشد و در آن عمده‌ی مشکلات به همراه نگارش 2007 آن برطرف شده است همانند Outlook web access سازگار با تمامی مرورگرهای امروزی، امکان مدیریت تحت وب صندوق‌های پستی کاربران، بازنگری در گزینه‌های تضمین فعالیت بی‌وقفه و ساده سازی آن‌ها، افزایش تعداد بانک‌های اطلاعاتی قابل تعریف در یک سرور و بسیاری از موارد دیگر که در طی چندین فصل به بررسی آن‌ها خواهیم پرداخت.

لینک دریافت: exchange2010.v1.rar

مطالب
استفاده از Web Fonts در اپلیکیشن های ASP.NET MVC

Typography در طراحی وب

برای بسیاری از توسعه دهندگان، طراحی یک اپلیکیشن وب شاید مقوله زیاد جالبی نباشد. مگر آنکه با طراحان حرفه ای سر و کار داشته باشند، و یا خودشان در زمینه طراحی فعال و با استعداد باشند. توسعه دهندگان می‌توانند به راحتی از اهمیت یا نیاز به Typography بگذرند، و تنها روی المان‌های گرافیکی پایه ای وقت بگذارند که در اپلیکیشن وب نهایتا استفاده خواهند شد.

به همین دلیل است که فریم ورک‌های HTML/CSS هر روزه محبوب‌تر می‌شوند. فریم ورک هایی مانند Twitter Bootstrap, HTML5 Boilerplate, Foundation و غیره. این فریم ورک‌ها طراحی و ساخت اپلیکیشن‌های وب را ساده‌تر و سریع‌تر می‌کنند، چرا که بسیاری از نیازهای رایج در طراحی وب پیاده سازی شده اند و دیگر نیازی به اختراع مجدد آنها نیست. اما به غیر از طراحی وب سایتی با ظاهری شیک و پسندیده، مقوله Typography شاید آخرین چیزی باشد که توسعه دهندگان به آن فکر می‌کنند.

Typography می‌تواند ظاهر بصری و تجربه کاربری را بسیار بهتر کند. انتخاب font-type‌‌های مناسب، وزن و استایل آنها می‌تواند به القای ایده ها، اهمیت مطالب و احساسات به کاربر کمک کند. همچنین خوانایی و درک مطالب شما هم بهبود می‌یابد، که همگی به کیفیت کلی طراحی شما کمک خواهند کرد.

انتخاب و استفاده از فونت ها
چالش انتخاب فونت برای وب، این است که باید بدانید آنها دقیقا چگونه برای کاربران رندر می‌شوند. برای اینکه فونت‌های شما همانطور که قصد دارید رندر شوند، مرورگر کاربر باید به فایل فونت‌ها دسترسی داشته باشد. ممکن است این فونت‌ها در سیستم عاملی که مرورگر در آن اجرا می‌شود، وجود نداشته باشند یا دسترسی به آنها ممکن نباشد.

طراحان وب طی سالیان متمادی، از فونت هایی استفاده می‌کردند که احتمال وجود آنها روی بازه گسترده ای از کامپیوتر‌ها زیاد بود. اینگونه فونت‌ها با عنوان 'web-safe' یاد می‌شوند:
  • Arial
  • Courier New
  • Helvetica
  • Times New Roman
  • Trebuchet
  • Georgia
  • Verdana
این لیست کوتاه، تنوع بسیار محدودی را در اختیار طراحان قرار می‌داد. برای رفع این محدودیت تکنیک‌های مختلفی استفاده می‌شد. مثلا متون مورد نظر را بصورت تصویر درج می‌کردند، یا با استفاده از افزونه ای در مرورگر از فونت خاصی استفاده می‌شد. مشکل عمده این روش‌ها این بود که متون مورد نظر قابل انتخاب و جستجو نبودند.

Web Fonts
یکی از راه حل‌ها برای رفع این محدودیت، توسعه فونت‌های وب بود. فونت‌های وب روی هر پلفترمی قابل استفاده هستند و توسط یک درخواست HTTP بارگذاری می‌شوند. با استفاده از فونت‌های وب، متون ما قابل انتخاب، جستجو و ترجمه به زبان‌های دیگر هستند. ناگفته نماند که بازه type-face‌‌های بسیار گسترده‌تری هم در دست داریم. از طرف دیگر به دلیل اینکه اکثر مرورگرهای وب امروزی از Web Fonts پشتیبانی می‌کنند، می‌توان اطمینان داشت که خروجی مورد نظر تقریبا روی تمام پلتفرم‌ها یکسان خواهد بود.

استفاده از فونت‌های وب در اپلیکیشن‌های ASP.NET MVC
خوب، چگونه می‌توانیم از فونت‌های وب در اپلیکیشن‌های MVC استفاده کنیم؟ در ادامه یک نمونه را بررسی میکنیم.
1. یک سرویس فونت انتخاب کنید. سرویس دهندگان زیادی وجود دارند که فونت‌های وب رایگان و پولی متنوعی را فراهم می‌کنند. برخی از سرویس دهندگان محبوب:
در مثال جاری از سرویس Typekit استفاده خواهیم کرد. نحوه استفاده از دیگر سرویس‌ها هم تقریبا یکسان است.
2. فونت مورد نظر را انتخاب کنید. سرویس‌های مذکور کتابخانه‌های بزرگی از فونت‌های وب دارند، که توسط رابط کاربری قوی آنها می‌توانید رندر نهایی فونت‌ها را مشاهده کنید. همچنین می‌توانید لیست فونت‌های موجود را بر اساس پارامترهای مختلفی مانند خواص، طبقه بندی، توصیه شده‌ها و غیره فیلتر کنید. برای مثال جاری فونت Bistro Script Web را انتخاب می‌کنیم.

3. کد جاوا اسکریپت خود را تولید کنید (تمام سرویس دهندگان این امکان را پیاده سازی کرده اند).

4. قطعه کد جاوا اسکریپت تولید شده را، در قسمت <head> فایل (Layout.cshtml (Razor_ یا (Site.Master (ASPX کپی کنید.

5. CSS Selector‌‌های لازم برای فونت مورد نظر را تولید کنید.

6. کد css تولید شده را در فایل Site.css کپی کنید. در مثال جاری فونت کل اپلیکیشن را تغییر می‌دهیم. برای اینکار، خانواده فونت "bistro-script-web" را به تگ body اضافه می‌کنیم.

نکته: فونت cursive بعنوان fallback تعریف شده. یعنی در صورتی که بارگذاری و رندر فونت مورد نظر با خطا مواجه شد، از این فونت استفاده می‌شود. بهتر است فونت‌های fallback به مقادیری تنظیم کنید که در اکثر پلتفرم‌ها وجود دارند.

همین! حالا می‌توانیم تغییرات اعمال شده را مشاهده کنیم. بصورت پیش فرض قالب پروژه‌ها از فونت "Segoe UI" استفاده می‌کنند، که خروجی زیر را رندر می‌کند.

استفاده از فونت جدید "Bistro Script Web" وب سایت را مانند تصویر زیر رندر خواهد کرد.

همانطور که می‌بینید استفاده از فونت‌های وب بسیار ساده است. اما بهتر است از اینگونه فونت‌ها برای کل سایت استفاده نشود و تنها روی المنت‌های خاصی مانند سر تیتر‌ها (h1,h2,etc) اعمال شوند.

نظرات مطالب
تفاوت بین IQueryable و IEnumerable در حین کار با ORMs
این‌ها بیشتر مباحث طراحی API است. اگر از List استفاده کنید، مصرف کننده کتابخانه شما مجبور است فقط از List استفاده کند. List صرفا یک پیاده سازی خاص از IList است.
اگر از اینترفیس و قرارداد IList استفاده شود، آزادی عمل بیشتری را در اختیار مصرف کننده خواهید گذاشت. در اینجا مصرف کننده می‌تواند از هر پیاده سازی دلخواهی از IList برای کار با API شما استفاده کند. حتی مواردی که در زمان طراحی API اصلی وجود خارجی نداشته‌اند و بعدها پیاده سازی خواهند شد.

مطالب
امن سازی برنامه‌های ASP.NET Core توسط IdentityServer 4x - قسمت اول - نیاز به تامین کننده‌ی هویت مرکزی
عصر Thick Clients

امن سازی برنامه‌های وب همواره چالش برانگیز بوده‌است؛ خصوصا این روزها که نیاز است برنامه‌ها، خارج از دیوارهای یک شرکت نیز در دسترس باشند و توسط انواع و اقسام وسایل ارتباطی مورد استفاده قرار گیرند. در سال‌های قبل، عموما برنامه‌های thick clients مانند WPF و WinForms برای شرکت‌ها توسعه داده می‌شدند و یا برنامه‌های وب مانند ASP.NET Web Forms که مبتنی بر سرویس‌ها نبودند. در برنامه‌های ویندوزی، پس از لاگین شخص به شبکه و دومین داخلی شرکت، عموما از روش Windows Authentication برای مشخص سازی سطوح دسترسی کاربران استفاده می‌شود. در برنامه‌های Web Forms نیز بیشتر روش Forms Authentication برای اعتبارسنجی کاربران مرسوم است. امن سازی این نوع برنامه‌ها ساده‌است. عموما بر روی یک دومین ارائه می‌شوند و کوکی‌های اعتبارسنجی کاربران برای ارائه‌ی مباحثی مانند single sign-on (داشتن تنها یک صفحه‌ی لاگین برای دسترسی به تمام برنامه‌های شرکت)، میسر است.


عصر شروع به‌کارگیری سرویس‌های وب

در سال‌های اخیر این شیوه‌ی کاری تغییر کرده و بیشتر بر اساس بکارگیری برنامه‌های مبتنی بر سرویس‌ها شده‌است. برای مثال برای این مورد استاندارد WS-Security مربوط به WCF ارائه شده‌است که باز هم مرتبط است به برنامه‌های یک دومین و یا یک Application pool. اگر تعداد دومین‌ها بیشتر شوند و نیاز به ارتباط امن بین آن‌ها باشد، استاندارد SAML 2.0 مورد استفاده قرار می‌گرفت که هدف از آن، انتقال امن اعتبارسنجی و سطوح دسترسی کاربران بین دومین‌های مختلف است. همانطور که ملاحظه می‌کنید تمام این برنامه‌ها و استانداردها، داخل دیوارهای یک شرکت و یک دومین زندگی می‌کنند.


عصر شروع به‌کارگیری Restful-API's

پس از آن باز هم شیوه‌ی طراحی برنامه‌های تغییر کرد و شروع به ایجاد Restful-API's و HTTP API's کردیم. این‌ها دیگر الزاما داخل یک دومین ارائه نمی‌شوند و گاهی از اوقات حتی تحت کنترل ما هم نیستند. همچنین برنامه‌های ارائه شده نیز دیگر thick clients نیستند و ممکن است برنامه‌های سمت کلاینت Angular و یا حتی موبایل باشند که مستقیما با سرویس‌های API برنامه‌ها کار می‌کنند. حتی ممکن است یک API را طراحی کنیم که با یک API دیگر کار می‌کند.


در این حالت دیگر نمی‌توان این APIها را با نگهداری آن‌ها داخل دیوارهای یک شرکت محافظت کرد. اگر قرار است با یک HTTP API کار کنیم، این API باید عمومی باشد و در اینجا دیگر نمی‌توان از روش Forms Authentication استفاده کرد. زیرا این روش اعتبارسنجی مختص برنامه‌های سمت سرور قرار گرفته‌ی در یک دومین طراحی شده‌است و آنچنان سازگاری با برنامه‌های سمت کلاینت و موبایل خارج از دیوارهای آن ندارد. همچنین ارسال نام کاربری و کلمه‌ی عبور به ازای هر درخواست نیز روشی بسیار بدوی و نا امن است. اینجا است که عصر امن سازی برنامه‌ها به کمک توکن‌ها شروع می‌شود. با استفاده‌ی از توکن‌ها، بجای هر بار ارسال نام کاربری و کلمه‌ی عبور به ازای هر درخواست از API، صرفا لیست سطوح دسترسی امضا شده‌ی به امکاناتی خاص، ارسال می‌شوند.


عصر شروع به‌کارگیری Security Tokens

بنابراین در اینجا نیاز به برنامه‌ای برای تولید توکن‌ها و ارسال آن‌ها به کلاینت‌ها داریم. روش متداول پیاده سازی آن، ساخت یک برنامه‌ی ابتدایی، برای دریافت نام کاربری و کلمه‌ی عبور از کاربران و سپس بازگشت یک JSON Web Token به آن‌ها است که بیانگر سطوح دسترسی آن‌ها به قسمت‌های مختلف برنامه است و کاربران باید این توکن را به ازای هر درخواستی به سمت سرور (بجای نام کاربری و کلمه‌ی عبور و خود) ارسال کنند.
مشکل این روش در اینجا است که آن برنامه‌ی خاص، باید از نام کاربری و کلمه‌ی عبور کاربران مطلع باشد تا بتواند توکن مناسبی را برای آن کاربر خاص تولید کند. هر چند این روش برای یک تک برنامه‌ی خاص بسیار مناسب به نظر می‌رسد، اما در یک شرکت، ده‌ها برنامه مشغول به کارند و به اشتراک گذاری نام کاربری و کلمه‌ی عبور کاربران، با تک تک آن‌ها ایده‌ی مناسبی نیست و پس از مدتی از کنترل خارج خواهد شد. برای مثال کاربری در یک برنامه، کلمه‌ی عبور خود را تغییر می‌دهد اما در برنامه‌ای دیگر خیر و همین مساله‌ی عدم هماهنگی بین برنامه‌ها و همچنین بخش‌های مختلف یک شرکت، مدیریت یک دست برنامه‌ها را تقریبا غیر ممکن می‌کند. همچنین در اینجا برنامه‌های ثالث را نیز باید در نظر داشت که آیا ضروری است آن‌ها به ریز اطلاعات کاربران شرکت دسترسی پیدا کنند؟
به علاوه مشکل دیگر توسعه‌ی این نوع برنامه‌های صدور توکن خانگی، اختراع مجدد چرخ است. در اینجا برای بهبود امنیت برنامه باید منقضی شدن، تمدید، امضای دیجیتال و اعتبارسنجی توکن‌ها را خودمان پیاده سازی کنیم. توسعه‌ی یک چنین سیستمی اگر غیرممکن نباشد، بسیار سخت و پیچیده است و همچنین باید باگ‌های امنیتی ممکن را نیز مدنظر داشت.


بنابراین تا اینجا به این نتیجه رسیده‌ایم که دیگر نمی‌خواهیم مدیریت نام کاربری و کلمه‌ی عبور کاربران را در سطح هیچکدام از برنامه‌های خود انجام دهیم و هیچکدام از آن‌ها قرار نیست دریافت کننده‌ی این اطلاعات باشند. قرار است این کار، به یک تک برنامه‌ی مرکزی مخصوص اینکار منتقل شود و برای اینکار نیاز به پروتکلی امن است که بتوان این توکن‌های تولیدی را ارسال و پردازش کرد.


حرکت به سمت «تامین کننده‌ی هویت مرکزی»


در گذشته، هر تک برنامه‌ای دارای صفحه‌ی لاگین و امکانات مدیریت کاربران آن، تغییر کلمه‌ی عبور، تنظیم مجدد آن و این‌گونه عملیات بود. این‌روزها دیگر چنین کاری مرسوم نیست. این وظیفه‌ی برنامه‌ی شما نیست که بررسی کند کاربر وارد شده‌ی به سیستم کیست و آیا ادعای او صحیح است یا خیر؟ این نوع عملیات وظیفه‌ی یک Identity provider و یا به اختصار IDP است. کار IDP اعتبارسنجی کاربر و در صورت نیاز، ارائه‌ی اثبات هویت کاربر، به برنامه‌ی درخواست کننده‌است.
در یک IDP عملیاتی مانند ثبت کاربران و مدیریت آن‌ها انجام می‌شود. اینجا است که مفاهیمی مانند قفل کردن اکانت و یا تغییر کلمه‌ی عبور و امثال آن انجام می‌شود و نه اینکه به ازای هر برنامه‌ی تهیه شده‌ی برای یک شرکت، آن برنامه راسا اقدام به انجام چنین عملیاتی کند. به این ترتیب می‌توان به امکان استفاده‌ی مجدد از اطلاعات هویت کاربران و سطوح دسترسی آن‌ها در بین تمام برنامه‌های موجود رسید.
همچنین با داشتن یک برنامه‌ی IDP خوب پیاده سازی شده، از توزیع باگ‌های امنیتی مختلف در بین برنامه‌های گوناگون تهیه شده که هر کدام سیستم امنیتی خاص خودشان را دارند، جلوگیری خواهد شد. برای مثال فرض کنید می‌خواهید الگوریتم هش کردن پسوردهای سیستم را که امروز نا امن اعلام شده‌است، تغییر دهید. با داشتن یک IDP، دیگر نیازی نیست تا تمام برنامه‌های خود را برای رفع یک چنین باگ‌هایی، تک تک تغییر دهید.


به علاوه این روزها روش استفاده‌ی از نام کاربری و کلمه‌ی عبور، تنها راه ورود به یک سیستم نیست و استفاده از کلیدهای دیجیتال و یا روش‌های ویژه‌ی ابزارهای موبایل نیز به این لیست اضافه شده‌اند.


حرکت به سمت استاندارد OAuth 2

OAuth 2.0 پروتکلی است استاندارد، برای Authorization امن کاربران، توسط برنامه‌های وب، موبایل و دسکتاپ. به این ترتیب می‌توان امکان دسترسی یک برنامه را به یک API، به نحوی استاندارد و امن میسر ساخت. OAuth 2.0 یک توکن دسترسی (Access token) را تولید می‌کند و در اختیار کلاینت قرار می‌دهد. سپس آن کلاینت با ارسال این توکن به API مدنظر، امکان دسترسی به امکانات مختلف آن‌را خواهد یافت. به علاوه چون ماهیت برنامه‌های کلاینت وب و غیر وب متفاوت است، این استاندارد نحوه‌ی دریافت چنین توکنی را برای برنامه‌های مختلف نیز تعریف می‌کند. به این ترتیب موارد مشترکی مانند تولید و نحوه‌ی انتقال توکن‌ها به کلاینت‌های مختلف توسط این پروتکل استاندارد بیان می‌شود. در این حالت راه‌حل‌های خانگی ما تبدیل به راه‌حل‌هایی می‌شوند که استاندارد OAuth 2.0 را پیاده سازی کرده باشند. بنابراین IDP ما باید بر مبنای این استاندارد تهیه شده باشد. برای مثال IdentityServer که در این سری بررسی خواهد شد و یا Azure Active Directory، نمونه‌ای از IDPهایی هستند که این استاندارد را کاملا پیاده سازی کرده‌اند.
البته باید دقت داشت که این توکن‌های دسترسی، تنها سطوح دسترسی به منابع API را مشخص می‌کنند و یا به عبارتی عملیات Authorization توسط آن‌ها میسر می‌شود. عملیات ورود به سیستم اصطلاحا Authentication نام دارد و توسط استاندارد دیگری به نام OpenID Connect مدیریت می‌شود.


حرکت به سمت استاندارد OpenID Connect


OpenID Connect یک لایه‌ی امنیتی بر فراز پروتکل OAuth 2.0 است که به اختصار به آن OIDC نیز گفته می‌شود. توسط آن یک کلاینت می‌تواند یک Identity token را علاوه بر Access token درخواست کند. از این Identity token برای ورود به برنامه‌ی کلاینت استفاده می‌شود (Authentication) و پس از آن، برنامه‌ی کلاینت بر اساس سطوح دسترسی تعریف شده‌ی در Access token، امکان دسترسی به امکانات مختلف یک API را خواهد یافت (Authorization). همچنین OpenID Connect امکان دسترسی به اطلاعات بیشتری از یک کاربر را نیز میسر می‌کند.
بنابراین OpenID Connect پروتکلی است که در عمل استفاده می‌شود و توسعه دهنده و جایگزین کننده‌ی پروتکل OAuth 2.0 می‌باشد. هرچند ممکن است در بسیاری از منابع صرفا به OAuth 2.0 بپردازند، اما در پشت صحنه با همان OpenID Connect کار می‌کنند.
مزیت دیگر کار با OpenID Connect، عدم الزام به استفاده‌ی از API، در برنامه‌ای خاص و یا قدیمی است. اگر برنامه‌ی وب شما با هیچ نوع API ایی کار نمی‌کند، باز هم می‌توانید از امکانات OpenID Connect بهره‌مند شوید.