نمایش قسمتی از صفحه بر اساس وضعیت اعتبارسنجی کاربر
فرض کنید میخواهیم در کامپوننت Shared\LoginDisplay.razor که در قسمت قبل آنرا اضافه کردیم، لینکهای ثبت نام و لاگین را به کاربران غیر اعتبارسنجی شده (هنوز لاگین نکرده) نمایش دهیم و اگر کاربر، اعتبارسنجی شده بود (لاگین کرده بود)، لینک خروج را به او نمایش دهیم. برای این منظور کامپوننت Shared\LoginDisplay.razor را به صورت زیر تغییر میدهیم:
<AuthorizeView> <Authorized> <a href="Identity/Account/Logout">Logout</a> </Authorized> <NotAuthorized> <a href="Identity/Account/Register">Register</a> <a href="Identity/Account/Login">Login</a> </NotAuthorized> </AuthorizeView>
البته اگر برنامه را در همین حالت اجرا کنیم، به استثنای زیر خواهیم رسید:
InvalidOperationException: Authorization requires a cascading parameter of type Task<AuthenticationState>. Consider using CascadingAuthenticationState to supply this. Microsoft.AspNetCore.Components.Authorization.AuthorizeViewCore.OnParametersSetAsync()
بنابراین به فایل BlazorServer.App\App.razor که محل تعریف ریشهی مسیریابی برنامهاست، مراجعه کرده و کامپوننت آنرا با کامپوننت توکار CascadingAuthenticationState محصور میکنیم:
<CascadingAuthenticationState> <Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> </Found> <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p>Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router> </CascadingAuthenticationState>
اکنون اگر برنامه را اجرا کنیم، مشاهده خواهیم کرد که در اولین بار مراجعهی به آن (پیش از لاگین)، لینک به صفحهی خروج، نمایش داده نشدهاست؛ چون آنرا در فرگمنت مخصوص Authorized قرار دادیم:
آزمایش نمایش منوی خروج برنامه
برای آزمایش برنامه، نیاز است ابتدا یک کاربر جدید را ثبت کنیم؛ چون هنوز هیچ کاربری در آن ثبت نشدهاست و همچنین کاربر پیشفرضی را هم به همراه ندارد. در مورد روش ثبت کاربران پیشفرض ASP.NET Core Identity، میتوانید به مطلب «بازنویسی متد مقدار دهی اولیهی کاربر ادمین در ASP.NET Core Identity توسط متد HasData در EF Core» مراجعه کنید و تمام نکات آن، در اینجا هم صادق است (چون پایهی سیستم Identity مورد استفاده، یکی است و هدف ما در اینجا بیشتر بررسی نکات یکپارچه سازی آن با Blazor Server است و نه مرور تمام نکات ریز Identity).
بنابراین ابتدا از منوی بالای صفحه، گزینهی Register را انتخاب کرده و کاربری را ثبت میکنیم. پس از ثبت نام، بلافاصله به منوی جدید زیر میرسیم که در آن گزینههای ورود و ثبت نام، مخفی شدهاند و اکنون گزینهی خروج از سیستم را نمایش میدهد:
بهبود تجربهی کاربری خروج از سیستم
در همین حال که گزینهی خروج نمایش داده شدهاست، اگر بر روی لینک آن کلیک کنیم، ابتدا ما را به صفحهی مجزای logout هدایت میکند. سپس باید در این صفحه، مجددا بر روی لینک logout بالای آن کلیک کنیم. زمانیکه اینکار را انجام دادیم، اکنون صفحهی دیگری را نمایش میدهد که به همراه پیام «خروج موفقیت آمیز از سیستم» است! در این پروسه، کاربر احساس میکند که کاملا از برنامهی اصلی خارج شدهاست و همچنین مراحل طولانی را نیز باید طی کند.
مدیریت این مراحل توسط دو فایل زیر انجام میشوند:
Areas\Identity\Pages\Account\Logout.cshtml
Areas\Identity\Pages\Account\Logout.cshtml.cs
میخواهیم کدهای این دو فایل را به نحوی تغییر دهیم که اگر کاربری بر روی لینک logout برنامهی اصلی کلیک کرد، به صورت خودکار logout شده و سپس مجددا به صفحهی اصلی برنامهی Blazor Server هدایت شود و مجبور نباشد تا مراحل طولانی یاد شده را تکرار کند.
به همین جهت ابتدا فایل Logout.cshtml.cs را حذف میکنیم؛ چون نیازی به آن نداریم. سپس محتوای فایل Logout.cshtml را به صورت زیر تغییر میدهیم:
@page @using Microsoft.AspNetCore.Identity @inject SignInManager<IdentityUser> SignInManager @functions { public async Task<IActionResult> OnGet() { if (SignInManager.IsSignedIn(User)) { <p>You have successfully logged out of the application.</p> await SignInManager.SignOutAsync(); } return Redirect("~/"); } }
نمایش User Claims، در یک برنامهی Blazor Server
سیستم ASP.NET Core Identity، بر اساس User Claims کار میکند؛ اطلاعات بیشتر. پس از استفاده از CascadingAuthenticationState در بالاترین سطح برنامه، اطلاعات آن در سراسر برنامهی Blazor Server هم قابل دسترسی است. برای مثال در کامپوننت Shared\LoginDisplay.razor، به نحو زیر میتوان نام کاربر ثبت نام شده را که یکی از User Claims او است، نمایش داد:
<AuthorizeView> <Authorized> Hello, @context.User.Identity.Name <a href="Identity/Account/Logout">Logout</a> </Authorized>
محدود کردن دسترسی به صفحات برنامه تنها برای کاربران اعتبارسنجی شده
پس از لاگین موفق به سیستم، اکنون میخواهیم دسترسی به صفحات تعریف اتاقها و یا امکانات رفاهی هتل را تنها به کاربران لاگین شده، محدود کنیم. برای اینکار تنها کافی است از ویژگی Authorize استفاده کنیم. برای مثال به کامپوننت Pages\HotelRoom\HotelRoomList.razor مراجعه کرده و یک سطر زیر را به آن اضافه میکنیم:
@attribute [Authorize]
مشکل! با اینکه تمام کامپوننتهای مثال جاری را به ویژگی Authorize مزین کردهایم، اما ... کار نمیکند! و هنوز هم میتوان بدون لاگین به سیستم، به محتوای آنها دسترسی داشت.
برای رفع این مشکل، مجددا نیاز است کامپوننت BlazorServer.App\App.razor را ویرایش کرد:
<CascadingAuthenticationState> <Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"> <Found Context="routeData"> @*<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />*@ <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> <NotAuthorized> <p>Sorry, you do not have access to this page</p> </NotAuthorized> </AuthorizeRouteView> </Found> <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p>Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router> </CascadingAuthenticationState>
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: Blazor-5x-Part-22.zip