Plik _ViewImports.cshtml pełni rolę globalnej deklaracji przestrzeni nazw i importów, co eliminuje konieczność powtarzania tych deklaracji na każdej stronie z osobna. Po zapoznaniu się z ogólną strukturą projektu i sposobem zarządzania stronami Razor, możemy przejść do praktycznych modyfikacji na przykładzie strony Index oraz powiązanego modelu IndexModel, aby zrozumieć, jak składnia Razor współdziała z kodem C#.

Strony Razor składają się z dwóch plików: pierwszy odpowiada za rendering interfejsu użytkownika, a drugi – za logikę biznesową. Możliwość osadzania kodu C# bezpośrednio w HTML pozwala na generowanie dynamicznego UI już podczas przetwarzania po stronie serwera, reagując na działania użytkownika.

W pliku index.cshtml między nawiasami @{ } definiujemy blok kodu C#, np. zmienną typu string:

csharp
string subtitle = "It's funny";

Kod umieszczony w tym bloku może zawierać zarówno instrukcje C#, jak i elementy HTML, co umożliwia warunkowe renderowanie, np.:

csharp
@{
if (total > 0) { <div>The available amount is: @total</div> } else { <div>There is no amount available</div> } }

Symbol @ pozwala także na wstawianie pojedynczych wyrażeń C# bezpośrednio w HTML, na przykład wyświetlenie wartości właściwości modelu:

csharp
@Model.Message @subtitle

Razor Pages udostępniają specjalne dyrektywy, takie jak asp-page-handler czy asp-route-id, które umożliwiają definiowanie obsługi zdarzeń i przekazywania parametrów w linkach i formularzach. Dynamiczne ustawianie stylów CSS, jak tło w elemencie div, również może odbywać się przez przypisanie wartości z modelu:

html
<div style="background-color:@Model.Color">...</div>

W prezentowanym przykładzie formularz HTML nie posiada atrybutu action, ponieważ konwencja Razor Pages zakłada, że dane formularza zostaną przesłane do tej samej strony, co upraszcza strukturę i obsługę żądań.

Generowanie tabeli produktów odbywa się za pomocą pętli foreach iterującej po kolekcji produktów w modelu:

csharp
@foreach (var product in Model.Products)
{ <tr> <td>@product.Id</td> <td>@product.Name</td> <td>@product.Price.ToString("C")</td> </tr> }

Formatowanie ceny uwzględnia lokalizację użytkownika, co pozwala na dostosowanie waluty i stylu liczbowego do ustawień przeglądarki. Dla bardziej precyzyjnego zarządzania kulturą aplikacji można ustawić ją globalnie w pliku Program.cs, stosując middleware UseRequestLocalization, co eliminuje potrzebę tworzenia dodatkowych właściwości formatujących.

Ważnym aspektem jest zachowanie odpowiedniego podziału obowiązków – kod odpowiedzialny za logikę biznesową powinien pozostać w modelu (plik .cshtml.cs), natomiast warstwa prezentacji (plik .cshtml) służy głównie do wyświetlania danych i zarządzania interakcją użytkownika. Dzięki temu utrzymujemy czytelność i łatwość konserwacji kodu.

Model strony Index dziedziczy po klasie PageModel, która dostarcza podstawowe właściwości i metody niezbędne dla funkcjonowania stron Razor. Dodanie właściwości i metod w pliku index.cshtml.cs umożliwia obsługę akcji i zarządzanie danymi wyświetlanymi w UI.

Endtext

Jakie mechanizmy zapewniają bezpieczeństwo aplikacji webowych w ASP.NET Core 9?

W podejściu DevOps, które koncentruje się na stałej dostawie wartości, bezpieczeństwo stało się jednym z kluczowych zagadnień. W ramach tej kultury pracy, zespoły programistyczne rezygnują z silosów, współpracują i dzielą się wiedzą, co sprzyja ciągłemu uczeniu się. W kontekście rozwoju aplikacji, temat bezpieczeństwa zyskuje na znaczeniu, przestając być odosobnionym zagadnieniem, traktowanym wyłącznie przez zespoły zajmujące się cyberbezpieczeństwem. Bezpieczeństwo stało się integralną częścią całego procesu tworzenia oprogramowania, począwszy od wczesnych etapów projektowania, aż po jego finalną implementację.

Współczesne standardy dotyczące bezpieczeństwa, takie jak ogólne rozporządzenie o ochronie danych osobowych (RODO) w Europie, pokazują, jak istotnym elementem stało się zarządzanie danymi i kontrola nad aplikacjami. Z tego względu, bezpieczeństwo jest nie tylko technicznym wymogiem, ale także strategicznym czynnikiem decydującym o powodzeniu lub porażce przedsięwzięć biznesowych. W kontekście ASP.NET Core 9, platforma ta oferuje szereg narzędzi i mechanizmów, które pomagają przeciwdziałać zagrożeniom i budować aplikacje odporne na ataki.

Kluczowym zagadnieniem, które należy zrozumieć, jest to, w jaki sposób bezpieczeństwo aplikacji webowych działa na różnych poziomach. Zwykle aplikacja webowa składa się z dwóch głównych komponentów: frontend, odpowiedzialny za interakcję z użytkownikiem, oraz backend, który przetwarza logikę biznesową i zapewnia interakcję z bazą danych. Te dwa komponenty komunikują się za pomocą różnych mechanizmów, takich jak protokół HTTP, nagłówki, ciasteczka, przechowywanie danych lokalnych w przeglądarce czy same zapytania SQL. Każdy z tych elementów jest potencjalnym punktem wejścia dla atakujących, którzy mogą wykorzystać luki w zabezpieczeniach, aby przejąć kontrolę nad aplikacją lub uzyskać dostęp do wrażliwych danych.

Bezpieczeństwo aplikacji musi być rozważane nie tylko w kontekście komunikacji między komponentami, ale również w procesie programowania. Przykładem jest błędne zastosowanie dynamicznych zapytań SQL, które prowadzą do podatności na ataki typu SQL injection. Nawet jeśli intencje programisty były jak najlepsze, nieprawidłowe podejście do komunikacji z bazą danych może skutkować poważnymi konsekwencjami, takimi jak utrata danych. Atakujący, wykorzystując niewłaściwie zbudowane zapytanie SQL, mogą wstrzyknąć szkodliwy kod, który zniszczy dane lub umożliwi dostęp do nieautoryzowanych zasobów.

Przykładem podatności, którą warto omówić, jest kod narażony na atak SQL injection:

csharp
using System;
using System.Data.SqlClient; public class VulnerableDataAccess { private string connectionString = "TheConnectionString"; public void GetUserData(string username) { string query = "SELECT * FROM Users WHERE Username = '" + username + "'"; using (SqlConnection connection = new SqlConnection(connectionString)) { SqlCommand command = new SqlCommand(query, connection); try { connection.Open(); SqlDataReader reader = command.ExecuteReader(); while (reader.Read()) { Console.WriteLine(String.Format("{0}, {1}", reader["Username"], reader["Email"])); } reader.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } }

W tym przypadku zapytanie SQL jest konstruowane w sposób narażający je na wstrzyknięcie złośliwego kodu. Jeśli użytkownik wpisze coś w rodzaju '; DROP TABLE users; --, zapytanie SQL zostanie zmodyfikowane w sposób, który może usunąć całą tabelę użytkowników. Zmiana, która wydaje się prosta i bezpieczna, w rzeczywistości staje się poważnym zagrożeniem dla integralności aplikacji.

Aby uniknąć takich sytuacji, niezbędna jest praktyka przeglądów kodu, gdzie zespół inżynierów analizuje zmiany przed ich wdrożeniem. Tylko jeśli kod przejdzie testy jakościowe i spełnia wymagania bezpieczeństwa, może zostać włączony do głównej gałęzi kodu. Z kolei procesy automatyczne, takie jak analiza statyczna kodu, powinny być częścią każdego etapu integracji i dostarczania oprogramowania. Narzędzia takie jak SonarQube mogą pomóc w identyfikowaniu potencjalnych luk w zabezpieczeniach, zanim jeszcze kod trafi na środowisko produkcyjne.

W kontekście zabezpieczeń warto również przyjrzeć się modelowi bezpieczeństwa, który opiera się na dwóch kluczowych procesach: uwierzytelnianiu (authentication) i autoryzacji (authorization). Uwierzytelnianie polega na potwierdzeniu tożsamości użytkownika, natomiast autoryzacja decyduje o tym, do jakich zasobów i funkcji aplikacji użytkownik ma dostęp. Właściwa implementacja tych procesów jest niezbędna, aby uniknąć nieautoryzowanego dostępu do wrażliwych danych lub funkcji systemu.

W szczególności, w przypadku aplikacji takich jak platformy bankowe, które zarządzają poufnymi informacjami, nieprawidłowe zabezpieczenie mechanizmu logowania może prowadzić do poważnych konsekwencji. Każde niedopatrzenie w tym zakresie może skutkować nie tylko naruszeniem prywatności użytkowników, ale także poważnymi stratami finansowymi dla organizacji.

Bezpieczeństwo aplikacji nie kończy się na implementacji zabezpieczeń na poziomie kodu czy infrastruktury. Ważne jest, aby każda organizacja wdrożyła odpowiednią politykę bezpieczeństwa, która obejmuje procedury audytowe, testy penetracyjne oraz systematyczne szkolenia zespołów programistycznych i operacyjnych. Właściwa edukacja i świadomość zagrożeń są kluczowe dla zapobiegania atakom i utrzymania systemu w pełni zabezpieczonego.

Dlaczego warto wybrać ASP.NET Core 9 i jak przygotować środowisko programistyczne?

ASP.NET Core 9 to nowoczesna, wysoko wydajna i gotowa na chmurę platforma do tworzenia aplikacji webowych, rozwijana od 2016 roku i nieustannie udoskonalana. W odróżnieniu od pierwotnych rozwiązań .NET Framework, które były ściśle powiązane z systemem Windows, ASP.NET Core umożliwia tworzenie aplikacji na wiele systemów operacyjnych – Windows, macOS oraz Linux – co otwiera zupełnie nowe możliwości i daje programistom większą swobodę wyboru środowiska pracy.

Przygotowanie odpowiedniego środowiska programistycznego jest fundamentalne dla efektywnej pracy z ASP.NET Core 9. Wymaga ono instalacji nie tylko samej platformy .NET SDK, ale również narzędzi takich jak Visual Studio Code lub Visual Studio, Docker, Git i Postman. Ponadto, integracja z platformą chmurową Microsoft Azure pozwala na łatwe wdrażanie i zarządzanie aplikacjami w środowisku produkcyjnym. Wszystkie te komponenty współdziałają ze sobą, tworząc kompleksowy ekosystem pracy nad nowoczesnymi aplikacjami.

Korzystanie z repozytoriów GitHub stanowi istotny element workflow programisty. W książce prezentowane są przykładowe kody dostępne pod adresem https://github.com/PacktPublishing/ASP.NET-Core-9.0-Essentials, co pozwala na samodzielne pisanie kodu i unikanie błędów wynikających z kopiowania. To podejście sprzyja głębszemu zrozumieniu omawianych zagadnień oraz umożliwia śledzenie aktualizacji wprowadzanych do materiałów.

W pracy z kodem stosowane są określone konwencje, które pomagają czytelnikowi zorientować się, kiedy mowa o fragmentach kodu, nazwach plików czy też komendach do wpisania w konsoli. Ważne słowa, nowe terminy czy elementy interfejsu użytkownika są wyróżniane pogrubieniem, co ułatwia nawigację i skupienie uwagi na kluczowych aspektach.

Znajomość różnic między .NET Framework a .NET (w tym ASP.NET Core 9) pozwala lepiej zrozumieć ewolucję technologii oraz przyczyny, dla których warto inwestować czas i zasoby w naukę nowszych narzędzi. .NET Core, a w jego najnowszej odsłonie ASP.NET Core 9, stawia na modularność, wydajność i multiplatformowość, co jest odpowiedzią na dynamiczne wymagania rynku IT i potrzeby programistów.

Istotne jest, by przed rozpoczęciem nauki lub pracy nad projektami posiadać komputer z uprawnieniami administratora oraz stabilny dostęp do internetu. Te elementy zapewniają bezproblemową instalację niezbędnego oprogramowania oraz możliwość korzystania z zasobów online, w tym z repozytoriów kodu czy usług chmurowych.

W kontekście dalszego rozwoju warto zwrócić uwagę na podstawowe komponenty platformy, takie jak Razor Pages, MVC, Blazor, Web API oraz SignalR, które umożliwiają tworzenie dynamicznych interfejsów użytkownika, usług sieciowych oraz komunikację w czasie rzeczywistym. Opanowanie tych technologii pozwala na pełne wykorzystanie możliwości ASP.NET Core 9 w praktyce.

Ważne jest, aby nie ograniczać się tylko do przyswajania podanych informacji, lecz rozumieć ich miejsce w szerszym ekosystemie rozwoju aplikacji. Wiedza o narzędziach, ich konfiguracji i współdziałaniu z platformą jest kluczowa dla efektywnego tworzenia, testowania i wdrażania nowoczesnych rozwiązań. Utrzymywanie aktualnej wersji oprogramowania oraz korzystanie z oficjalnych źródeł i aktualizacji to podstawa bezpieczeństwa i stabilności projektów.

Jak CNCF Wspiera Rozwój Aplikacji Cloud-Native: Przykład Pracy z ASP.NET Core 9 na Microsoft Azure

CNCF (Cloud Native Computing Foundation) oferuje ogromne zasoby dla organizacji i profesjonalistów zajmujących się tworzeniem aplikacji opartych na chmurze. Jednym z najważniejszych zasobów CNCF jest "landscape" technologiczny, który jest interaktywnym przewodnikiem mapującym ekosystem cloud-native. Przedstawia on narzędzia, projekty i technologie powiązane z misją CNCF, oferując wgląd w szeroki wachlarz rozwiązań dostępnych w chmurze. To potężne narzędzie pozwala lepiej zrozumieć dostępne opcje, ich zależności oraz role w ekosystemie cloud-native.

Aby lepiej zrozumieć, jak CNCF może wspierać proces rozwoju aplikacji, przeanalizujmy scenariusz rozwoju aplikacji webowej przy użyciu ASP.NET Core 9, hostowanej na platformie Microsoft Azure. Taki przykład pozwala pokazać, jak wykorzystać narzędzia CNCF, by aplikacja była zgodna z zasadami cloud-native, a jednocześnie korzystała z najlepszych dostępnych narzędzi do wdrażania, monitorowania i zarządzania.

Strategia konteneryzacji

Pierwszym krokiem w tworzeniu aplikacji opartej na chmurze jest konteneryzacja. W tym przypadku decydujemy się na użycie Docker’a, technologii wspieranej przez CNCF, aby zapakować aplikację i jej zależności w kontener. Docker zapewnia spójność w różnych środowiskach, takich jak deweloperskie, testowe czy produkcyjne. Dzięki temu proces zarządzania zależnościami staje się łatwiejszy, a aplikacja jest odizolowana od środowiska, w którym jest uruchamiana. Dzięki Docker’owi aplikacja może działać wszędzie tam, gdzie dostępny jest silnik Docker, zapewniając niezmienność środowisk.

Korzyści:

  • Zapewnienie spójności aplikacji pomiędzy środowiskami.

  • Ułatwienie zarządzania zależnościami oraz izolacja komponentów.

Orkiestracja kontenerów z Kubernetes

Aby aplikacja mogła działać w chmurze, konieczna jest orkiestracja kontenerów. W tym przypadku wybieramy Kubernetes, kolejny projekt CNCF, który automatycznie zarządza cyklem życia kontenerów, skalowaniem oraz równoważeniem obciążenia. Azure Kubernetes Service (AKS) oferuje zarządzane środowisko Kubernetes, co upraszcza wdrażanie, zarządzanie i skalowanie aplikacji kontenerowych. AKS korzysta ze standardów ustalonych przez CNCF, a jednocześnie upraszcza tworzenie klastra Kubernetes, oferując dodatkowe usługi.

Korzyści:

  • Automatyczne zarządzanie cyklem życia kontenerów oraz skalowaniem aplikacji.

  • Zapewnienie wysokiej dostępności i odporności systemu.

Automatyzacja procesów CI/CD

W celu uproszczenia procesu tworzenia aplikacji, decydujemy się na użycie narzędzi do automatyzacji procesów CI/CD, takich jak Jenkins lub GitHub Actions. Narzędzia te automatyzują procesy budowania, testowania i wdrażania aplikacji, dzięki czemu zmiany w kodzie są szybciej wprowadzane na środowisko produkcyjne. Proces CI/CD redukuje ryzyko błędów wynikających z ręcznych interwencji i pozwala na płynne zarządzanie wersjami aplikacji.

Korzyści:

  • Automatyzacja procesów wdrożeniowych, co zapewnia spójność i zmniejsza ryzyko błędów.

  • Przyspieszenie cyklu rozwoju aplikacji, umożliwiając ciągłą integrację i wdrażanie.

Monitoring i logowanie

Po zakończeniu etapu rozwoju aplikacji i wdrożeniu jej na środowisko produkcyjne, kluczowym krokiem jest implementacja narzędzi do monitorowania i logowania. W tym przypadku wykorzystujemy Prometheus i Grafanę, które są projektami incubatorowymi CNCF. Prometheus zbiera metryki, a Grafana je wizualizuje, umożliwiając uzyskanie wglądu w zachowanie aplikacji. Azure Monitor, również narzędzie z obszaru CNCF, oferuje podobną funkcjonalność. Dodatkowo, OpenTelemetry, także wspierane przez CNCF, pozwala na zbieranie danych w sposób niezależny od dostawcy chmurowego, co zwiększa elastyczność aplikacji.

Korzyści:

  • Real-time monitoring i powiadomienia o stanie aplikacji.

  • Szybsza diagnoza problemów z wydajnością i łatwiejsze rozwiązywanie problemów.

Wykorzystanie CNCF w tym scenariuszu pozwala na stworzenie rozwiązania chmurowego, które jest skalowalne, odporne na awarie i łatwe w utrzymaniu. Docker, Kubernetes, Prometheus, Grafana, Jenkins i GitHub Actions to tylko niektóre z narzędzi, które wspierają rozwój aplikacji cloud-native, zgodnych z najlepszymi praktykami i standardami określonymi przez CNCF.

Azure Agnostycyzm

Chociaż omawiany scenariusz zakłada hosting aplikacji na platformie Microsoft Azure, narzędzia użyte w tym przykładzie są agnostyczne wobec dostawcy chmurowego. Oznacza to, że rozwiązanie może zostać przeniesione na inną platformę chmurową, ponieważ wszystkie narzędzia, takie jak Kubernetes, Docker czy Prometheus, działają na różnych chmurach i zgodne są ze standardami CNCF, które zapewniają interoperacyjność. Ważne jest, by regularnie odwiedzać stronę CNCF, aby być na bieżąco z nowinkami w zakresie modeli chmurowych oraz dostępnych narzędzi. To pozwala na tworzenie coraz potężniejszych rozwiązań, które odpowiadają na rosnące potrzeby organizacji i rynku.

Przyjęcie zasad twelve-factor app

Ważnym aspektem, który pomaga tworzyć aplikacje cloud-native, są zasady "twelve-factor app". Te zasady, stworzone przez twórców platformy Heroku, to zestaw najlepszych praktyk, które pomagają w budowaniu aplikacji łatwych do wdrożenia, skalowalnych i łatwych w utrzymaniu. Obejmują one takie zagadnienia jak kontrola wersji kodu, izolacja zależności, przechowywanie konfiguracji w środowisku oraz traktowanie usług wspierających jako zasoby przyłączone do aplikacji. Zasady te powinny być implementowane we wszystkich etapach cyklu życia aplikacji.

Wdrożenie tych zasad w praktyce z użyciem narzędzi CNCF pozwala na stworzenie elastycznych i łatwych do zarządzania aplikacji, które mogą działać w różnych środowiskach chmurowych, z zachowaniem najwyższych standardów jakości i niezawodności.