Blazor istemci tarafı kimlik doğrulama eğitimindeki eksik parça.

Paylaş :

Zamanında, Blazor'da kimlik doğrulamayı öğrenmeye başladığımda, hemen hemen her öğretici bir Blazor Sunucu projesi oluşturmaktan, Kimlik çerçevesini kullanmaktan ve SUNUCU tarafında bazı CURD işlemlerinden bahsettiği için hayal kırıklığına uğradım. Hey, Blazor öğrenen insanlar büyük olasılıkla C# geliştiricileri olduğundan, sunucu tarafında kimlik doğrulamanın nasıl yapıldığını biliyorum, Blazor'u tam yığın C# fırsatları için öğreniyoruz, bu nedenle React/Vue/Angular dışında ön uç kodu oluşturmak için ek seçeneğimiz var.

Blazor istemci tarafı kimlik doğrulama eğitimindeki eksik parça.

Bu, Blazor istemci tarafı kimlik doğrulama öğreticisinin eksik parçasıdır ve aşağıdaki soruları yanıtlar:

  • Her kullanıcının varsayılan olarak bu sayfaya gideceği bir giriş ekranı nasıl oluşturulur?
  • Oturum açmadıklarında diğer ekranlar kullanıcı erişiminden nasıl gizlenir?

Not : İstemci tarafı kimlik doğrulaması hassastır, buna bağlı değildir. Bu makalenin amacı güvenlikle ilgili değil, tamamen kullanıcı arayüzü ile ilgili. Hem istemci hem de sunucu tarafı için güvenlik güçlendirme konusunda İnternette bulabileceğiniz birçok ipucu ve püf noktası vardır.


adımlar

  1. Gerekli bağımlılıklar:
  • Microsoft.AspNetCore.Authorization
  • Microsoft.AspNetCore.Components.Yetkilendirme
  • Microsoft.AspNetCore.Components.WebAssembly.Authentication

Bir Blazor wasm projesi oluşturalım. Bu projede .NET 6 kullanıyoruz.

dotnet new blazorwasm
dotnet add package Microsoft.AspNetCore.Authorization
dotnet add package Microsoft.AspNetCore.Components.Authorization
dotnet add package AspNetCore.Components.WebAssembly.Authentication


2. MyCustomAuthenticationStateProvider oluşturun

  • AuthenticationStateProvider  itibaren uzanmalıdır 
  • Varsayılan kullanıcıyı geçersiz kıl GetAuthenticationStateAsync() ve herhangi bir hak talebi olmayan anonim bir kullanıcıya ayarla.
  • Sahte oturum açma ve sahte kullanıcılar hazırlayın.

public class MyAuthenticationStateProvider : AuthenticationStateProvider {
    public override async Task<AuthenticationState> GetAuthenticationStateAsync() {
        return await Task.FromResult(new AuthenticationState(AnonymousUser));
    }

    //Anonymous user can has no claims but requires an empty identity
    private ClaimsPrincipal AnonymousUser => new(new ClaimsIdentity(Array.Empty<Claim>()));
    private ClaimsPrincipal FakedUser {
        get {
            var claims = new[] {
                new Claim(ClaimTypes.Name, "john"),
                new Claim(ClaimTypes.Role, "user"),
            };
            var identity = new ClaimsIdentity(claims, "faked");
            return new ClaimsPrincipal(identity);
        }
    }
    private ClaimsPrincipal FakedAdmin {
        get {
            var claims = new[] {
                new Claim(ClaimTypes.Name, "john"),
                new Claim(ClaimTypes.Role, "admin"),
            };
            var identity = new ClaimsIdentity(claims, "faked");
            return new ClaimsPrincipal(identity);
        }
    }
    public void FakedSignIn() {
        var result = Task.FromResult(new AuthenticationState(FakedUser));
        NotifyAuthenticationStateChanged(result);
    }
    public void FakedAdminSignIn() {
        var result = Task.FromResult(new AuthenticationState(FakedAdmin));
        NotifyAuthenticationStateChanged(result);
    }
    public void FakedSignOut() {
        var result = Task.FromResult(new AuthenticationState(AnonymousUser));
        NotifyAuthenticationStateChanged(result);
    }
}


Bu sınıf, tüm sihrin gerçekleştiği yerdir. Bu makalenin ilerleyen kısımlarında buna döneceğiz.

3. Program.cs'yi Yapılandır

Bu satırları şuraya eklememiz gerekiyor Program.cs:



builder.Services.AddScoped<MyAuthenticationStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(provider => provider.GetRequiredService<MyAuthenticationStateProvider>());

builder.Services.AddAuthorizationCore();

Bir nesneyi nasıl başlattığımıza MyAuthenticationStateProviderve onu AuthenticationStateProvider.

Aksi takdirde AuthenticationStateProvider, uygulamamız yerine Blazor tarafından varsayılan bir nesne kullanılacaktır.

4. Kurulum _Imports.razor



@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Authorization

// Note that the fully qualified namespace is needed. Missing the project prefix will cause Components not able to run.

@using blazor_wasm_client_auth.Pages

@attribute [Authorize]

@attribute[Authorized]Tüm sayfaların varsayılan olarak yetkilendirme gerektirmesi için buraya yerleştirdiğimiz notu.

5. Giriş ekranı oluşturun

@page "/login"
@attribute [AllowAnonymous]

[AllowAnonymous]Kullanıcının oturum açmadan erişimine izin vermek için özniteliği buraya yerleştirmemiz gerektiğini unutmayın .

Ardından, normal kullanıcı ve yönetici kullanıcı için oturum açmayı simüle etmek için iki düğmemiz var:



<button class="btn btn-primary" @onclick="OnNormalLoginClicked">Login as normal user</button>
<button class="btn btn-primary" @onclick="OnAdminLoginClicked">Login as admin</button>



private void OnNormalLoginClicked() {

    _authenticationStateProvider.FakedSignIn();

    _navigationManager.NavigateTo("/");

}

private void OnAdminLoginClicked(MouseEventArgs obj) {

    _authenticationStateProvider.FakedAdminSignIn();

    _navigationManager.NavigateTo("/");

}

6. RedirectToLogin bileşeni oluşturun

/login Bu, kullanıcıyı sayfaya geri yönlendirmek için boş bir bileşendir .



protected override void OnInitialized() {
 _navigationManager.NavigateTo("/login");

}

7. MainLayout'u şununla sarın:<AuthorizeView>

"MainLayout.razor" içindeki orijinal içeriği "Yetkili" etiketiyle sarıyoruz:



<Authorized>
<div class="page">

      <div class="sidebar">

          <NavMenu />

      </div>

      <main>

          <div class="top-row px-4">

              <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>

          </div>

          <article class="content px-4">

              @Body

          </article>

      </main>

  </div>

</Authorized>

8. Yalnızca yönetici içeriğini dahil etNavMenu

' Shared/NavMenu.razorde orijinal linki fetchDataekrana <AuthorizeView>etiketi ile saracağız ve bu linki görmek için gerekli rolü “ admin ” olarak ayarlayacağız. Ayrıca kullanıcının çıkış yapması için bir düğme ekledik.




 <AuthorizeView Roles="admin">
<div class="nav-item px-3">

        <h6>Secret Message for Admin only.</h6>

        <NavLink class="nav-link" href="fetchdata">

            <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data

        </NavLink>

    </div>

</AuthorizeView>

9. Yönlendirmeyi şununla sarın:<AuthorizeRouteView>

içinde , etiketi etiketle App.razordeğiştirin . Ardından bileşenimizi etiketin içine yerleştirin. Bu nedenle, bir kullanıcı var olan ancak henüz yetkilendirilmemiş bir rotaya eriştiğinde, Blazor onları tekrar oturum açma ekranına yönlendirecektir.<RouteView><AuthorizeRouteView>RedirectToLogin<NotAuthorized>



<AuthorizeRouteView RouteData="@routeData" DefaultLayout="typeof(MainLayout)">
<NotAuthorized>

        <RedirectToLogin />

    </NotAuthorized>

    <Authorizing>

        Authorizing...

    </Authorizing>

</AuthorizeRouteView>

10. Eşleşmeyen rotalar için yapılandırma eylemi.

, etiketini App.razordoldurduğunuzdan emin olun, NotFoundbir kullanıcı mevcut olmayan bir rotaya erişmeye çalıştığında Blazor bunu yapacaktır. Kullanıcı erişmeye çalışırsa /something-not-exist, içinde olmayan yalnızca etiketin [‘/','/counter’,'/fetchData','/login']içine ne koyduğunuzu gösterir . <NotFound>Bizim durumumuzda, “ Sayfa bulunamadı ” mesajını görüntüler.



<NotFound>
<PageTitle>Not found</PageTitle>

    <div>Page not found.</div>

</NotFound>

11. Koş ve kendini test et

  1. ile projemizi çalıştırın ve test edin dotnet run.
  2. Tarayıcıyı açın ve Blazor uygulamamızın kök dizinine gidin.
  3. Talep etmenize rağmen /şimdi sayfaya yönlendirildiğinize dikkat /loginedin.

Bunun nedeni, şu kodlara sahip olmamızdır App.razor:


Rota /içinde tanımlandı , bu nedenle etikete Index.razordüşüyor . <Found>Ve sonra giriş yapmadığımız için, daha fazla etikete düşüyor ve sonunda bileşene <NotAuthorized>indik . <RedirectToLogin />Bileşen başlatıldığında, _navigationManager.NavigateTo("/login"). Bu yüzden giriş ekranını görüyoruz.

Şimdi tarayıcımızın adres çubuğuna gidin, hiçbir sayfada tanımlı olmayan bir rota yazın. (örneğin “https://localhost:5000/something-not-exist”).

Hiçbir rota eşleşmediğinden, App.razoretikete girin <NotFound>ve yalnızca sayfanın bulunamadığını belirten bir mesaj göreceğiz.

Hakkında MyAuthenticationStateProvider:

Bu sınıf bir yöntemi genişletir AuthenticationStateProviderve geçersiz kılar:



<NotAuthorized>
<RedirectToLogin />

</NotAuthorized>

Kullanıcı yetkili sayfaya erişmeye çalıştığında bu yöntem çağrılır. Blazor, geçerli kullanıcının hangi taleplere sahip olduğunu ve kullanıcının belirli sayfalara erişmesine izin verip vermediğini belirlemek için bir AuthenticationState nesnesi arayacaktır.

Nesne , kullanıcı adı, roller vb. gibi taleplere sahip AuthenticationStatebir nesne bekler .ClaimsPrincipal

Bir ClaimsPrincipalnesnenin herhangi bir iddiası yoksa, anonim bir kullanıcı olarak kabul edilir. Bu, kullandığımız hile MyAuthenticationStateProvider:


Son olarak, giriş ekranımıza dönün ve farklı giriş butonunu deneyin.

Normal oturum açma düğmesine tıkladığınızda, gezinme menüsünde veri getir bağlantısını görmezsiniz.

Çıkış düğmesine tıklayın ve giriş sayfasına geri döneceğiz.

Şimdi yönetici giriş düğmesine tıklayın. Bu sefer navigasyon menüsünde veri getir bağlantısını göreceğiz.

Bunun nedeni, sahte ClaimPrinciple nesnemizin "admin" olarak ClaimTypes.Role ayarlanmış olması ve getirme veri bağlantısını "admin" olarak oluşturmak için gereken rolleri ayarlamış olmamızdır:<AuthorizViews Roles="admin">

Hesabınızı yönetmek için giriş yapın

veya