اشتراک‌ها
چرا Microsoft SQL Server و چرا MySQL Server ؟

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

چرا Microsoft SQL Server و چرا MySQL Server ؟
مطالب
تغییر نام پایگاه داده و فایل هایش در SQL Server 2012
بعضی وقت‌ها به هر علتی لازم است پایگاه داده و فایل هایش را تغییر نام دهیم. اگر در اینترنت جستجو کنیم روش‌های مختلفی برای تغییر نام مثل تغییر  با Management Studio  یا T-SQL یا روش‌های دیگری یافت می‌شود. اما اکثرا در بین انجام به مشکلی غیر قابل پیش بینی بر می‌خوریم. پایگاه داده در حالت آفلاین یا Pending قرار گرفته و به خطا‌های نا مفهومی بر می‌خوریم. حالا باید دوباره کلی جستجو کنیم تا مشکل بوجود آمده را حل نمائیم.

بهترین روش تغییر نام پایگاه داده
بهترین روش استفاده از قابلیت Copy Database خود SQL Server است است که به راحتی این کار را برای ما انجام می‌دهد.
  1. بر روی پایگاه داده مورد نظر راست کلیک کرده و از گزینه Tasks گزینه Copy Database را انتخاب کنید.
  2. پس از ظاهر شدن پنجره کپی گزینه Next را انتخاب و در مرحله مبدا و مقصد، سرور جاری را انتخاب کنید و به مرحله بعد بروید.
    این برای زمانی است که شما می‌خواهید پایگاه داده را در سرور دیگری کپی نماید
  3. در پنجره Transfer Method دو روش Detach and Attach  و استفاده از SQL Management Object  وجود دارد که با همان روش اول به مرحله بعد بروید

  4.  در مرحله بعد نام پایگاه داده شما انتخاب شده به مرحله بعد بروید.
  5. مرحله بعد پیکریندی پایگاه داده مقصد می‌باشد که نام و مسیر پایگاه داده جدید را می‌توانید مشخص نمایید.

  6. این عملیات با SQL Server Agent صورت می‌پذیرد به همین خاطر Agent می‌بایست نصب و Start شده باشد.
  7. با انتخاب گزینه Next مراحل بعد را رد کرده تا عملیات آغاز شود.
  8. در مرحله آخر پایگاه داده قبلی را حذف نمایید.

نظرات مطالب
امن سازی برنامه‌های ASP.NET Core توسط IdentityServer 4x - قسمت نهم- مدیریت طول عمر توکن‌ها
اگر بخواهیم بعد از تغییر کلمه عبور، لاگین فرد در همه کلاینت‌ها غیر معتبر شود - چیزی معادل این مطلب در ASP.NET Identity - آیا با پیاده سازی   Reference Token  امکان پذیر است؟
مطالب
Blazor 5x - قسمت 23 - احراز هویت و اعتبارسنجی کاربران Blazor Server - بخش 3 - کار با نقش‌های کاربران
در قسمت قبل، روش یکپارچه سازی context مربوط به ASP.NET Core Identity را با یک برنامه‌ی Blazor Server، بررسی کردیم. در این قسمت می‌خواهیم محدود کردن دسترسی‌ها را بر اساس نقش‌های کاربران و همچنین کدنویسی مستقیم، بررسی کنیم.


کار با Authentication State از طریق کدنویسی

فرض کنید در کامپوننت HotelRoomUpsert.razor نمی‌خواهیم دسترسی‌ها را به کمک اعمال ویژگی attribute [Authorize]@ محدود کنیم؛ می‌خواهیم اینکار را از طریق کدنویسی مستقیم انجام دهیم:
// ...

@*@attribute [Authorize]*@


@code
{
    [CascadingParameter] public Task<AuthenticationState> AuthenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        var authenticationState = await AuthenticationState;
        if (!authenticationState.User.Identity.IsAuthenticated)
        {
            var uri = new Uri(NavigationManager.Uri);
            NavigationManager.NavigateTo($"/identity/account/login?returnUrl={uri.LocalPath}");
        }
        // ...
- در اینجا در ابتدا اعمال ویژگی Authorize را کامنت کردیم.
- سپس یک پارامتر ویژه را از نوع CascadingParameter، به نام AuthenticationState تعریف کردیم. این خاصیت از طریق کامپوننت CascadingAuthenticationState که در قسمت قبل به فایل BlazorServer.App\App.razor اضافه کردیم، تامین می‌شود.
- در آخر در روال رویدادگردان OnInitializedAsync، بر اساس آن می‌توان به اطلاعات User جاری وارد شده‌ی به سیستم دسترسی یافت و برای مثال اگر اعتبارسنجی نشده بود، با استفاده از NavigationManager، او را به صفحه‌ی لاگین هدایت می‌کنیم.
- در اینجا روش ارسال آدرس صفحه‌ی فعلی را نیز مشاهده می‌کنید. این امر سبب می‌شود تا پس از لاگین، کاربر مجددا به همین صفحه هدایت شود.

authenticationState، امکانات بیشتری را نیز در اختیار ما قرار می‌دهد؛ برای مثال با استفاده از متد ()authenticationState.User.IsInRole آن می‌توان دسترسی به قسمتی را بر اساس نقش‌های خاصی محدود کرد.


ثبت کاربر ادمین Identity

در ادامه می‌خواهیم دسترسی به کامپوننت‌های مختلف را بر اساس نقش‌ها، محدود کنیم. به همین جهت نیاز است تعدادی نقش و یک کاربر ادمین را به بانک اطلاعاتی برنامه اضافه کنیم. برای اینکار به پروژه‌ی BlazorServer.Common مراجعه کرده و تعدادی نقش ثابت را تعریف می‌کنیم:
namespace BlazorServer.Common
{
    public static class ConstantRoles
    {
        public const string Admin = nameof(Admin);
        public const string Customer = nameof(Customer);
        public const string Employee = nameof(Employee);
    }
}
علت قرار دادن این کلاس در پروژه‌ی Common، نیاز به دسترسی به آن در پروژه‌ی اصلی Blazor Server و همچنین در پروژه‌ی سرویس‌های برنامه‌است. فضای نام این کلاس را نیز در فایل imports.razor_ قرار می‌دهیم.

سپس در فایل BlazorServer.App\appsettings.json، مشخصات ابتدایی کاربر ادمین را ثبت می‌کنیم:
{
  "AdminUserSeed": {
    "UserName": "vahid@dntips.ir",
    "Password": "123@456#Pass",
    "Email": "vahid@dntips.ir"
  }
}
جهت دریافت strongly typed این تنظیمات در برنامه، کلاس معادل AdminUserSeed را به پروژه‌ی Models اضافه می‌کنیم:
namespace BlazorServer.Models
{
    public class AdminUserSeed
    {
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
    }
}
که به صورت زیر در فایل BlazorServer.App\Startup.cs به سیستم تزریق وابستگی‌های برنامه معرفی می‌شود:
namespace BlazorServer.App
{
    public class Startup
    {

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions<AdminUserSeed>().Bind(Configuration.GetSection("AdminUserSeed"));
            // ...
اکنون می‌توان سرویس افزودن نقش‌ها و کاربر ادمین را در پروژه‌ی BlazorServer.Services تکمیل کرد:
using System;
using System.Linq;
using System.Threading.Tasks;
using BlazorServer.Common;
using BlazorServer.DataAccess;
using BlazorServer.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

namespace BlazorServer.Services
{
    public class IdentityDbInitializer : IIdentityDbInitializer
    {
        private readonly ApplicationDbContext _dbContext;
        private readonly UserManager<IdentityUser> _userManager;
        private readonly RoleManager<IdentityRole> _roleManager;
        private readonly IOptions<AdminUserSeed> _adminUserSeedOptions;

        public IdentityDbInitializer(
            ApplicationDbContext dbContext,
            UserManager<IdentityUser> userManager,
            RoleManager<IdentityRole> roleManager,
            IOptions<AdminUserSeed> adminUserSeedOptions)
        {
            _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
            _roleManager = roleManager ?? throw new ArgumentNullException(nameof(roleManager));
            _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
            _adminUserSeedOptions = adminUserSeedOptions ?? throw new ArgumentNullException(nameof(adminUserSeedOptions));
        }

        public async Task SeedDatabaseWithAdminUserAsync()
        {
            if (_dbContext.Roles.Any(role => role.Name == ConstantRoles.Admin))
            {
                return;
            }

            await _roleManager.CreateAsync(new IdentityRole(ConstantRoles.Admin));
            await _roleManager.CreateAsync(new IdentityRole(ConstantRoles.Customer));
            await _roleManager.CreateAsync(new IdentityRole(ConstantRoles.Employee));

            await _userManager.CreateAsync(
                new IdentityUser
                {
                    UserName = _adminUserSeedOptions.Value.UserName,
                    Email = _adminUserSeedOptions.Value.Email,
                    EmailConfirmed = true
                },
                _adminUserSeedOptions.Value.Password);

            var user = await _dbContext.Users.FirstAsync(u => u.Email == _adminUserSeedOptions.Value.Email);
            await _userManager.AddToRoleAsync(user, ConstantRoles.Admin);
        }
    }
}
این سرویس، با استفاده از دو سرویس توکار UserManager و RoleManager کتابخانه‌ی Identity، ابتدا سه نقش ادمین، مشتری و کارمند را ثبت می‌کند. سپس بر اساس اطلاعات AdminUserSeed تعریف شده، کاربر ادمین را ثبت می‌کند. البته این کاربر در این مرحله، یک کاربر معمولی بیشتر نیست. در مرحله‌ی بعد است که با انتساب نقش ادمین به او، می‌توان کاربر او را بر اساس این نقش ویژه، شناسایی کرد. کلاس‌های IdentityRole و IdentityUser، کلاس‌های پایه‌ی نقش‌ها و کاربران کتابخانه‌ی Identity هستند.

پس از تعریف این سرویس، نیاز است آن‌را به سیستم تزریق وابستگی‌های برنامه اضافه کرد:
namespace BlazorServer.App
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<IIdentityDbInitializer, IdentityDbInitializer>();
            // ...
مرحله‌ی آخر، اعمال و اجرای سرویس IIdentityDbInitializer، در زمان آغاز برنامه‌است و محل توصیه شده‌ی آن، در متد Main برنامه‌ی اصلی، پیش از اجرای برنامه‌است. به همین جهت، نیاز است BlazorServer.DataAccess\Utils\MigrationHelpers.cs را به صورت زیر ایجاد کرد:
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Polly;

namespace BlazorServer.DataAccess.Utils
{
    public static class MigrationHelpers
    {
        public static void MigrateDbContext<TContext>(
                this IServiceProvider serviceProvider,
                Action<IServiceProvider> postMigrationAction
                ) where TContext : DbContext
        {
            using var scope = serviceProvider.CreateScope();
            var scopedServiceProvider = scope.ServiceProvider;
            var logger = scopedServiceProvider.GetRequiredService<ILogger<TContext>>();
            using var context = scopedServiceProvider.GetService<TContext>();

            logger.LogInformation($"Migrating the DB associated with the context {typeof(TContext).Name}");

            var retry = Policy.Handle<Exception>().WaitAndRetry(new[]
                {
                    TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15)
                });

            retry.Execute(() =>
                {
                    context.Database.Migrate();
                    postMigrationAction(scopedServiceProvider);
                });

            logger.LogInformation($"Migrated the DB associated with the context {typeof(TContext).Name}");
        }
    }
}
در مورد این متد و استفاده از Polly جهت تکرار عملیات شکست خورده پیشتر در مطلب «اضافه کردن سعی مجدد به اجرای عملیات Migration در EF Core» بحث شده‌است.
کار متد الحاقی فوق، دریافت یک IServiceProvider است که به سرویس‌های اصلی برنامه اشاره می‌کند. سپس بر اساس آن، یک Scoped ServiceProvider را ایجاد می‌کند تا درون آن بتوان با Context برنامه در طی مدت کوتاهی کار کرد و در پایان آن، سرویس‌های ایجاد شده را Dispose کرد.
در این متد ابتدا Database.Migrate فراخوانی می‌شود تا اگر مرحله‌ای از Migrations برنامه هنوز به بانک اطلاعاتی اعمال نشده، کار اجرا و اعمال آن انجام شود. سپس یک متد سفارشی را از فراخوان دریافت کرده و اجرا می‌کند. برای مثال توسط آن می‌توان IIdentityDbInitializer در فایل BlazorServer.App\Program.cs به صوت زیر فراخوانی کرد:
public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();
    host.Services.MigrateDbContext<ApplicationDbContext>(
     scopedServiceProvider =>
            scopedServiceProvider.GetRequiredService<IIdentityDbInitializer>()
                                 .SeedDatabaseWithAdminUserAsync()
                                 .GetAwaiter()
                                 .GetResult()
    );
    host.Run();
}
تا اینجا اگر برنامه را اجرا کنیم، سه نقش پیش‌فرض، به بانک اطلاعاتی برنامه اضافه شده‌اند:


و همچنین کاربر پیش‌فرض سیستم را نیز می‌توان مشاهده کرد:


که نقش ادمین و کاربر پیش‌فرض، به این صورت به هم مرتبط شده‌اند (یک رابطه‌ی many-to-many برقرار است):



محدود کردن دسترسی کاربران بر اساس نقش‌ها

پس از ایجاد کاربر ادمین و تعریف نقش‌های پیش‌فرض، اکنون محدود کردن دسترسی به کامپوننت‌های برنامه بر اساس نقش‌ها، ساده‌است. برای این منظور فقط کافی است لیست نقش‌های مدنظر را که می‌توانند توسط کاما از هم جدا شوند، به ویژگی Authorize کامپوننت‌ها معرفی کرد:
@attribute [Authorize(Roles = ConstantRoles.Admin)]
و یا از طریق کدنویسی به صورت زیر نیز قابل اعمال است:
    protected override async Task OnInitializedAsync()
    {
        var authenticationState = await AuthenticationState;
        if (!authenticationState.User.Identity.IsAuthenticated ||
            !authenticationState.User.IsInRole(ConstantRoles.Admin))
        {
            var uri = new Uri(NavigationManager.Uri);
            NavigationManager.NavigateTo($"/identity/account/login?returnUrl={uri.LocalPath}");
        }


کدهای کامل این مطلب را از اینجا می‌توانید دریافت کنید: Blazor-5x-Part-23.zip
مطالب
امن سازی برنامه‌های ASP.NET Core توسط IdentityServer 4x - قسمت سوم - بررسی مفاهیم OpenID Connect
پیش از نصب و راه اندازی IdentityServer، نیاز است با یک سری از مفاهیم اساسی پروتکل OpenID Connect، مانند Identity token ،Client types ،Flow و Endpoints، آشنا شویم تا بتوانیم از امکانات این IDP ویژه استفاده و آن‌ها را تنظیم کنیم. بدون آشنایی با این مفاهیم، اتصال برنامه‌ای که در قسمت قبل تدارک دیدیم به IdentityServer میسر نیست.


پروتکل OpenID Connect چگونه کار می‌کند؟

در انتهای قسمت اول این سری، پروتکل OpenID Connect معرفی شد. در ادامه جزئیات بیشتری از این پروتکل را بررسی می‌کنیم.
هر برنامه‌ی کلاینت متصل به WebAPI مثال قسمت قبل، نیاز به دانستن هویت کاربر وارد شده‌ی به آن‌را دارد. در اینجا به این برنامه‌ی کلاینت، اصطلاحا relying party هم گفته می‌شود؛ از این جهت که این برنامه‌ی کلاینت، به برنامه‌ی Identity provider و یا به اختصار IDP، جهت دریافت نتیجه‌ی اعتبارسنجی کاربر، وابسته‌است. برنامه‌ی کلاینت یک درخواست Authentication را به سمت IDP ارسال می‌کند. به این ترتیب کاربر به صورت موقت از برنامه‌ی جاری خارج شده و به برنامه‌ی IDP منتقل می‌شود. در برنامه‌ی IDP است که کاربر مشخص می‌کند کیست؛ برای مثال با ارائه‌ی نام کاربری و کلمه‌ی عبور. پس از این مرحله، در صورت تائید هویت کاربر، برنامه‌ی IDP یک Identity Token را تولید و امضاء می‌کند. سپس برنامه‌ی IDP کاربر را مجددا به برنامه‌ی کلاینت اصلی هدایت می‌کند و Identity Token را در اختیار آن کلاینت قرار می‌دهد. در اینجا برنامه‌ی کلاینت، این توکن هویت را دریافت و اعتبارسنجی می‌کند. اگر این اعتبارسنجی با موفقیت انجام شود، اکنون کاربر تعیین اعتبار شده و هویت او جهت استفاده‌ی از قسمت‌های مختلف برنامه مشخص می‌شود. در برنامه‌های ASP.NET Core، این توکن هویت، پردازش و بر اساس آن یکسری Claims تولید می‌شوند که در اغلب موارد به صورت یک کوکی رمزنگاری شده در سمت کلاینت ذخیره می‌شوند.
به این ترتیب مرورگر با هر درخواستی از سمت کاربر، این کوکی را به صورت خودکار به سمت برنامه‌ی کلاینت ارسال می‌کند و از طریق آن، هویت کاربر بدون نیاز به مراجعه‌ی مجدد به IDP، استخراج و استفاده می‌شود.


مراحل انتقال کاربر به IDP، صدور توکن هویت، بازگشت مجدد به برنامه‌ی کلاینت، اعتبارسنجی، استخراج Claims و ذخیره‌ی آن به صورت یک کوکی رمزنگاری شده را در تصویر فوق ملاحظه می‌کنید. بنابراین در حین کار با یک IDP، مرحله‌ی لاگین به سیستم، دیگر در برنامه یا برنامه‌های کلاینت قرار ندارد. در اینجا دو فلش به سمت IDP و سپس به سمت کلاینت را بخاطر بسپارید. در ادامه از آن‌ها برای توضیح Flow و Endpoints استفاده خواهیم کرد.

البته OpenID Connect برای کار همزمان با انواع و اقسام برنامه‌های کلاینت طراحی شده‌است؛ مانند برنامه‌ی سمت سرور MVC، برنامه‌های سمت کلاینت جاوا اسکریپتی مانند Angular و برنامه‌های موبایل. برای این منظور باید در IDP نوع کلاینت و یکسری از تنظیمات مرتبط با آن‌را مشخص کرد.


کلاینت‌های عمومی و محرمانه

زمانیکه قرار است با یک IDP کار کنیم، این IDP باید بتواند بین یک برنامه‌ی حسابداری و یک برنامه‌ی پرسنلی که از آن برای احراز هویت استفاده می‌کنند، تفاوت قائل شود و آن‌ها را شناسایی کند.

- کلاینت محرمانه (Confidential Client)
هر کلاینت با یک client-id و یک client-secret شناخته می‌شود. کلاینتی که بتواند محرمانگی این اطلاعات را حفظ کند، کلاینت محرمانه نامیده می‌شود.
در اینجا هر کاربر، اطلاعات هویت خود را در IDP وارد می‌کند. اما اطلاعات تعیین هویت کلاینت‌ها در سمت کلاینت‌ها ذخیره می‌شوند. برای مثال برنامه‌های وب ASP.NET Core می‌توانند هویت کلاینت خود را به نحو امنی در سمت سرور ذخیره کنند و این اطلاعات، قابل دسترسی توسط کاربران آن برنامه نیستند.

- کلاینت عمومی (Public Client)
این نوع کلاینت‌ها نمی‌توانند محرمانگی هویت خود را حفظ و تضمین کنند؛ مانند برنامه‌های جاوا اسکریپتی Angular و یا برنامه‌های موبایل که بر روی وسایل الکترونیکی کاربران اجرا می‌شوند. در این حالت هرچقدر هم سعی کنیم، چون کاربران به اصل این برنامه‌ها دسترسی دارند، نمی‌توان محرمانگی اطلاعات ذخیره شده‌ی در آن‌ها را تضمین کرد.


مفهوم OpenID Connect Endpoints

در تصویر ابتدای بحث، دو فلش را مشاهده می‌کنید؛ برای مثال چگونه می‌توان به Identity token دسترسی یافت (Authentication) و همچنین زمانیکه صحبت از Authorization می‌شود، چگونه می‌توان Access tokens را دریافت کرد. اینکه این مراحله چگونه کار می‌کنند، توسط Flow مشخص می‌شود. Flow مشخص می‌کند که چگونه باید توکن‌ها از سمت IDP به سمت کلاینت بازگشت داده شوند. بسته به نوع کلاینت‌ها که در مورد آن‌ها بحث شد و نیازمندی‌های برنامه، باید از Flow مناسبی استفاده کرد.
هر Flow با Endpoint متفاوتی ارتباط برقرار می‌کند. این Endpointها در حقیقت جایگزین راه‌حل‌های خانگی تولید برنامه‌های IDP هستند.
- در ابتدا یک Authorization Endpoint وجود دارد که در سطح IDP عمل می‌کند. این مورد همان انتهای فلش اول ارسال درخواست به سمت IDP است؛ در تصویر ابتدای بحث. کار این Endpoint، بازگشت Identity token جهت انجام عملیات Authentication و بازگشت Access token برای تکمیل عملیات Authorization است. این عملیات نیز توسط Redirection کلاینت انجام می‌شود (هدایت کاربر به سمت برنامه‌ی IDP، دریافت توکن‌ها و سپس هدایت مجدد به سمت برنامه‌ی کلاینت اصلی).

نکته‌ی مهم: استفاده‌ی از TLS و یا همان پروتکل HTTPS برای کار با OpenID Connect Endpoints اجباری است و بدون آن نمی‌توانید با این سیستم کار کنید. به عبارتی در اینجا ترافیک بین کلاینت و IDP، همواره باید رمزنگاری شده باشد.
البته مزیت کار با ASP.NET Core 2.1، یکپارچگی بهتر و پیش‌فرض آن با پروتکل HTTPS است؛ تا حدی که مثال پیش‌فرض local آن به همراه یک مجوز موقتی SSL نصب شده‌ی توسط SDK آن کار می‌کند.

- پس از Authorization Endpoint که در مورد آن توضیح داده شد، یک Redirection Endpoint وجود دارد. در ابتدای کار، کلاینت با یک Redirect به سمت IDP هدایت می‌شود و پس از احراز هویت، مجددا کاربر به سمت کلاینت Redirect خواهد شد. به آدرسی که IDP کاربر را به سمت کلاینت Redirect می‌کند، Redirection Endpoint می‌گویند و در سطح کلاینت تعریف می‌شود. برنامه‌ی IDP، اطلاعات تولیدی خود را مانند انواع توکن‌ها، به سمت این Endpoint که در سمت کلاینت قرار دارد، ارسال می‌کند.

- پس از آن یک Token Endpoint نیز وجود دارد که در سطح IDP تعریف می‌شود. این Endpoint، آدرسی است در سمت IDP، که برنامه‌ی کلاینت می‌تواند با برنامه نویسی، توکن‌هایی را از آن درخواست کند. این درخواست عموما از نوع HTTP Post بدون Redirection است.


مفهوم OpenID Connect Flow


- اولین Flow موجود، Authorization Code Flow است. کار آن بازگشت کدهای Authorization از Authorization Endpoint و همچنین توکن‌ها از طریق Token Endpoint می‌باشد. در ایجا منظور از «کدهای Authorization»، اطلاعات دسترسی با طول عمر کوتاه است. هدف Authorization Code این است که مشخص کند، کاربری که به IDP لاگین کرده‌است، همانی است که Flow را از طریق برنامه‌ی وب کلاینت، شروع کرده‌است. انتخاب این نوع Flow، برای کلاینت‌های محرمانه مناسب است. در این حالت می‌توان مباحث Refresh token و داشتن توکن‌هایی با طول عمر بالا را نیز پیاده سازی کرد.

- Implicit Flow، تنها توکن‌های تولیدی را توسط Authorization Endpoint بازگشت می‌دهد و در اینجا خبری از بازگشت «کدهای Authorization» نیست. بنابراین از Token Endpoint استفاده نمی‌کند. این نوع Flow، برای کلاینت‌های عمومی مناسب است. در اینجا کار client authentication انجام نمی‌شود؛ از این جهت که کلاینت‌های عمومی، مناسب ذخیره سازی client-secret نیستند. به همین جهت در اینجا امکان دسترسی به Refresh token و توکن‌هایی با طول عمر بالا میسر نیست. این نوع از Flow، ممکن است توسط کلاینت‌های محرمانه نیز استفاده شود.

- Hybrid Flow، تعدادی از توکن‌ها را توسط Authorization Endpoint و تعدادی دیگر را توسط Token Endpoint بازگشت می‌دهد؛ بنابراین ترکیبی از دو Flow قبلی است. انتخاب این نوع Flow، برای کلاینت‌های محرمانه مناسب است. در این حالت می‌توان مباحث Refresh token و داشتن توکن‌هایی با طول عمر بالا را نیز پیاده سازی کرد. از این نوع Flow ممکن است برای native mobile apps نیز استفاده شود.

آگاهی از انواع Flowها، انتخاب نوع صحیح آن‌ها را میسر می‌کند که در نتیجه منتهی به مشکلات امنیتی نخواهند شد. برای مثال Hybrid Flow توسط پشتیبانی از Refresh token امکان تمدید توکن جاری و بالا بردن طول عمر آن‌را دارد و این طول عمر بالا بهتر است به کلاینت‌های اعتبارسنجی شده ارائه شود. برای اعتبارسنجی یک کلاینت، نیاز به client-secret داریم و برای مثال برنامه‌های جاوا اسکریپتی نمی‌توانند محل مناسبی برای ذخیره سازی client-secret باشند؛ چون از نوع کلاینت‌های عمومی محسوب می‌شوند. بنابراین نباید از Hybrid Flow برای برنامه‌های Angular استفاده کرد. هرچند انتخاب این مساله صرفا به شما بر می‌گردد و چیزی نمی‌تواند مانع آن شود. برای مثال می‌توان Hybrid Flow را با برنامه‌های Angular هم بکار برد؛ هرچند ایده‌ی خوبی نیست.


انتخاب OpenID Connect Flow مناسب برای یک برنامه‌ی کلاینت از نوع ASP.NET Core

برنامه‌های ASP.NET Core، از نوع کلاینت‌های محرمانه به‌شمار می‌روند. بنابراین در اینجا می‌توان تمام Flowهای یاد شده را انتخاب کرد. در برنامه‌های سمت سرور وب، به ویژگی به روز رسانی توکن نیاز است. بنابراین باید دسترسی به Refresh token را نیز داشت که توسط Implicit Flow پشتیبانی نمی‌شود. به همین جهت از Implicit Flow در اینجا استفاده نمی‌کنیم. پیش از ارائه‌ی OpenID Connect، تنها Flow مورد استفاده‌ی در برنامه‌های سمت سرور وب، همان Authorization Code Flow بود. در این Flow تمام توکن‌ها توسط Token Endpoint بازگشت داده می‌شوند. اما Hybrid Flow نسبت به آن این مزیت‌ها را دارد:
- ابتدا اجازه می‌دهد تا Identity token را از IDP دریافت کنیم. سپس می‌توان آن‌را بدون دریافت توکن دسترسی، تعیین اعتبار کرد.
- در ادامه OpenID Connect این Identity token را به یک توکن دسترسی، متصل می‌کند.
به همین جهت OpenID Connect نسبت به OAuth 2 ارجحیت بیشتری پیدا می‌کند.

پس از آشنایی با این مقدمات، در قسمت بعدی، کار نصب و راه اندازی IdentityServer را انجام خواهیم داد.
اشتراک‌ها
ویژگی های SQL Server 2019 را در این ویدئو تماشا کنید!

In this video, you will get to experience bringing SQL and Spark together as a unified data platform running on Kubernetes and learn how:

• Data virtualization integrates data from disparate sources, locations and formats, without replicating or moving the data, to create a single "virtual" data layer

• Data Lake - SQL 2019 provides SQL and Spark query capabilities over a scalable storage, across relational and big data

• Data Mart provides an ability to scale out storage for super-fast performance over big data or data from other external sources 

ویژگی های SQL Server 2019 را در این ویدئو تماشا کنید!
مطالب
مروری بر Claim
تعریف :
در این پست قصد دارم در مورد claim که از آن به عنوان یک Abstraction برای شناسایی نام برده شده ، صحبت کنم و گریزی با ارتباط آن با شیرپوینت بزنم . مایکروسافت در جایی Claim را این گونه تعریف کرده بود : یک عبارت که یک شیئ ، آن را در باره خودش یا شیئ دیگری می‌سازد . Claim یک Abstraction برای شناسایی فراهم می‌کند . برای مثال میتوان گفت که یک عبارت که شامل نام ، شناسه ، کلید ، گروه بندی ، ظرفیت و ... باشد ، فراهم می‌کند .
 لازم است به تعریف Token هم اشاره ای شود . هنگامی که یک شناسه دیجیتالی در شبکه در حال گذر است ، فقط حاوی مجموعه ای از بایت‌ها است .( ارجاع به مجموعه ای از بایت‌ها که حاوی اطلاعات شناسایی به عنوان یک Token امنیتی با فقط یک Token باشد، امری عادی است ) . در محیطی که بر مبنای Claim بنا شده است ، یک Token حاوی یک یا چند Claim است که هر یک می‌تواند برخی تکه‌های اطلاعاتی را برای شناسایی (بیشتر در مورد کاربران و افراد استفاده می‌شود) ، در خود جای دهد  

Claim‌ها تقریبا هر چیزی را در مورد یک کاربر می‌تواند ارائه دهد. . برای مثال در Token تصویر بالا ، 3 claim اول به اطلاعات نام و نقش و سن کاربر اشاره دارند . 
فراهم کننده - توزیع کننده :
Claim‌ها توسط یک فراهم کننده (Provider) توزیع می‌شوند (Issuer) و سپس به آنها یک یا چند مقدار ، اختصاص می‌یابد و در Security Token هایی که توسط یک توزیع کننده ، توزیع می‌شوند ، بسته بندی می‌شود و معمولا به عنوان Security Token Service یا STS شناخته می‌شوند . برای مشاهده تعریف اصطلاحات مرتبط به Claim به اینجا مراجعه کنید 

STS ، می‌تواند توسط چند Identity Provider - IdP به مالکیت در بیاید . یک فراهم کننده شناسه در STS یا IP-STS ، یک سرویس است که درخواست‌ها را برای اطمینان از شناسایی Claim‌ها مدیریت می‌کند . یک IP-STS از یک پایگاه داده که Identity Store نامیده می‌شود برای نگهداری و مدیریت شناسه‌ها و خصیصه‌های مرتبط با آنها استفاده می‌کند .Identity Store می‌تواند یک دیتا بیس معمولی مانند SQL Server باشد یا یک محیط پیچیده‌تر مانند Active Directory . (از قبیل Active Directory Domain Services یا Active Directory Lightweight Directory Service ) . 
 
قلمرو - Realm
بیانگر مجموعه ای از برنامه‌ها ، URL‌ها ، دامنه‌ها یا سایت هایی می‌باشد که برای Token ، معتبر باشد .معمولا یک Realm با استفاده از دامنه (microsoft.com) یا مسیری داخل دامنه (microsoft.com/practices/guides) تعریف می‌شود .بعضی وقت‌ها یک realm ، به عنوان Security Domain بیان می‌شود چرا که تمام برنامه‌های داخل یک مرز امنیتی ویژه ای را احاطه کرده است .
 
Identity Federation
Identity Federation در حقیقت دریافت کننده Token هایی است که در خارج از Realm شما ایجاد شده اند و در صورتی Token را می‌پذیرد که شما Issuer یا توزیع کننده را مورد اطمینان معرفی کرده باشد . این امر به کاربران اجازه می‌دهد تا بدون نیاز به ورود به realm تعریف شده خودشان ، از realm دیگری وارد برنامه شوند . کاربران با یک بار ورود به محیط برنامه ، به چندین realm دسترسی پیدا خواهند کرد . 

Relying party application

هر برنامه سمت client که از Claim پشتیبانی کند 

مزایای Claim

  • جدا سازی برنامه از جزییات شناسایی
  • انعطاف پذیری در احراز هویت
  • Single sign-on
  • عدم نیاز به VPN
  • متحد کردن مجموعه با دیگر شرکت ها
  • متحد کردن مجموعه با سرویس‌های غیر از AD 

عناصر Claim

Claim شامل عناصر زیر می‌باشد :

  • Token
  • Claim
  • Provider/Issuer
    • Sharepoint STS
    • ADFS
    • ACS
    • OID
    • ,و غیره 
توزیع کننده‌ی ADFS

  
پرنکل‌ها و Token‌های Claim
شاید این بخش ، یکی از سردرگم کننده‌ترین مفاهیم باشد . هنگامی که صحبت از Claim می‌شود ، عده ای دچار این عدم توجه صحیح می‌شوند که هر دو نوع مختلفی از Token‌ها که با Claim‌ها استفاده می‌شوند ، توسط تمام برنامه‌ها پشتیبانی نمی‌شوند . نکته قابل توجه نوع پروتکلی است که می‌خواهید از آن استفاده کنید و باید کامل از آن مطلع باشید .
Security Token هایی که در اینترنت رفت و آمد می‌کنند ، معمولا یکی از دو نوع زیر هستند :
 - توکن‌های Security Assertion Markup Language یا SAML که ساختار XMLی دارند و encode شده اند و داخل ساختارهای دیگر از قبیل پیغام‌های HTTP و SOAP جای می‌گیرند
 - Simple Web Token یا SWT که درون هدر‌های درخواست یا پاسخ HTTP جای میگیرند .(WS-Federation)
 
نوع متفاوتی از Token که وابسته به مکانیسم احراز هویت است، ایحاد شده است . برای مثال اگر از Claim با Windows Sign-in استفاده می‌کنید ، شیرپوینت 2010 ، شیئ UserIdentity را به شیئ ClaimIdentity نبدیل می‌کند و claim را تقویت کرده و Token حاصله را مدیریت می‌کند . (این نوع Toaken جزء SAML نمی‌شود)
 
تنها راه به گرفتن توکن‌های SAML ، استفاده از یک Provider برای SAML است . مانند Windows Live ID یا ADFS . [+ ] 

معماری برنامه‌های مبتنی بر Claim
نام مدل : Direct Hub Model 

نام مدل : Direct Trust Model
 

مزایا :
- مدیریت راحت‌تر برای multiple trust relationships دز ADFS نسبت به Sharepoint
- مدیریت ساده‌تر در single trust relationship در شیرپوینت و عدم نیاز به فراهم کننده‌های سفارشی سازی شده برای Claim
- قایلیت استفاده از ویژگی‌های ADFS برای پیگیری توزیع Token ها
- ADFS از هز دوی SAML و WS-Federation پشتیبانی می‌کند
- توزیع کننده ADFS اجازه می‌دهد تا خصیصه‌های LDAP را از AD استخراج کنید
- ADFS به شما اجازه استفاده از قواعد دستوری SQL را برای استخراج داده‌ها از دیگر پایگاه‌های داده می‌دهد
- کارایی و اجرای مناسب 

معایب :
- کند بودن
- عدم پشتیبانی از SAML-P
- نیازمند تعریف کاربر‌ها در AD یا نواحی مورد اطمینان