Search code examples
.netasp.net-coreblazor-client-sideblazor-webassembly

Blazor WebAssembly. Add Authorize attribute at layout level


I started from a visual studio template, a new Blazor WebAssembly with authentication and web API as the server-side.

My problem there is to protect all the pages and not just some pages. I tried to add :

@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]

to the MainLayout instead of all pages but without any luck. I wanted to do that because I'm writing an admin and I don't want people to see the layout at all if there are not connected


Solution

  • I wanted to do that because I'm writing an admin and I don't want people to see the layout at all if there are not connected

    It can be understood that when the user is not logged in, they cannot enter any page, so we can jump to the login page at this time,right?

    If so, you can achieve it by the following steps:

    • First create a RedirectToLogin.razor page in the current blazor project.

      In the OnInitializedAsync method of this page, by judging whether there is currently a user logged in, and if not, redirect to the Login page.

      RedirectToLogin.razor:

      @inject NavigationManager Navigation
      @code {
          [CascadingParameter]
          private Task<AuthenticationState> AuthenticationStateTask { get; set; }
      
          protected override async Task OnInitializedAsync()
          {
              var authenticationState = await AuthenticationStateTask;
      
              if (authenticationState?.User?.Identity is null || !authenticationState.User.Identity.IsAuthenticated)
              {
                  Navigation.NavigateTo("Identity/Account/Login", true);
              }
          }
      }
      
    • Then add the following code in App.razor to ensure that NotAuthorized will enter the RedirectToLogin.razor page:

      <CascadingAuthenticationState>
          <Router AppAssembly="@typeof(Program).Assembly">
              <Found Context="routeData">
                  <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                      <NotAuthorized>
                          <RedirectToLogin />
                      </NotAuthorized>
                  </AuthorizeRouteView>
              </Found>
              <NotFound>
                  <LayoutView Layout="@typeof(MainLayout)">
                      <p>Sorry, there's nothing at this address.</p>
                  </LayoutView>
              </NotFound>
          </Router>
      </CascadingAuthenticationState>
      
    • Finally, in the MainLayout.razor page, a distinction is made between Authorized and NotAuthorized:

      @inherits LayoutComponentBase
      <AuthorizeView>
          <Authorized>
              <div class="sidebar">
                  <NavMenu />
              </div>
      
              <div class="main">
                  <div class="top-row px-4 auth">
                      <LoginDisplay />
                      <a href="https://learn.microsoft.com/aspnet/" target="_blank">About</a>
                  </div>
      
                  <div class="content px-4">
                      @Body
                  </div>
              </div>
          </Authorized>
          <NotAuthorized>
              <RedirectToLogin />
          </NotAuthorized>
      </AuthorizeView>
      

    Here is the test result:

    enter image description here