SignalR er et kraftfuldt bibliotek fra .NET-platformen, der muliggør udvikling af applikationer med realtidsfunktioner. For at udvikle sådanne applikationer er det nødvendigt, at serveren og klienten konstant kan kommunikere via en aktiv kanal. SignalR gør det muligt at opbygge disse realtidsløsninger på en forenklet måde, så kommunikationen mellem klient og server kan ske konstant og i realtid.

SignalR fungerer ved at abstrahere den kommunikationsmodel, der ligger til grund for klient-server interaktioner. Forbindelsen mellem klienten og serveren opretholdes gennem en aktiv kanal, som transporterer JSON eller binære meddelelser. WebSockets er den primære kommunikationsmetode, der anvendes af SignalR, men hvis WebSockets ikke understøttes, bruges server-sent events eller long polling som fallback-muligheder. Prioriteten af transportmetoderne er som følger:

  1. WebSockets: Denne metode etablerer en fuld-dupleks-forbindelse, hvilket muliggør kontinuerlig kommunikation mellem server og klient.

  2. Server-sent events: Denne metode skaber en ensrettet forbindelse fra serveren til klienten, hvor klienten ikke kan sende beskeder tilbage til serveren over den samme forbindelse.

  3. Long polling: En grundlæggende teknik, hvor klienten sender en anmodning til serveren og modtager et svar, når serveren har behandlet anmodningen.

SignalR abstraherer valget af transportteknik og gør det muligt at definere præferencen for WebSockets, hvis det er nødvendigt. Kommunikation mellem klient og server styres af en vigtig komponent kaldet Hub. Hubs fungerer som proxyer, der muliggør fjernkommunikation mellem klient og server, hvor serveren kan udføre funktioner på klienten gennem Remote Procedure Calls (RPC). RPC er en kommunikationsprotokol, der har eksisteret siden 1970 og udgør grundlaget for moderne løsninger som gRPC, som blev udviklet af Google.

En væsentlig fordel ved SignalR er, at det abstraherer al kompleksiteten ved håndtering af forbindelser og kommunikation. Derudover giver det mulighed for at sende notifikationer til alle tilsluttede klienter, specifikke klienter eller grupper af klienter. Det er også muligt at bruge SignalR API'er i forbindelse med .NET-applikationer, men også Java, JavaScript eller konsolapplikationer. For eksempel kan en server kommunikere med en konsolapplikation, der er udviklet enten i .NET eller Java.

For at forstå de grundlæggende begreber og principper bag SignalR og dets anvendelse, lad os se på et eksempel, hvor vi bygger en opgavestyringsapplikation. Denne applikation vil implementere realtidsfunktioner som at oprette, afslutte og vise opgaver. Den server-side logik vil blive håndteret med C#, mens JavaScript bruges på klient-siden for at håndtere brugerinteraktionen. SignalR bliver central i at opretholde forbindelsen mellem klienten og serveren og sikre, at ændringer på serveren straks afspejles på klienten i realtid.

I en simpel applikation som en opgavestyringsapplikation, kan vi se, at både server og klient spiller vigtige roller. Klienten implementeres ved hjælp af Razor Pages, hvor brugerens interaktioner håndteres af JavaScript-filer, der kommunikerer med serveren. SignalR JavaScript SDK'en bruges til at etablere forbindelse til serveren og håndtere realtidsopdateringer. På serversiden fungerer Hub'en som den centrale enhed, der styrer kommunikationen og muliggør, at klienten og serveren kan udveksle oplysninger.

For at udvikle en sådan applikation, starter vi med at oprette et nyt .NET-projekt ved hjælp af kommandoen dotnet new webapp -o TaskManager. Efterfølgende installeres SignalR JavaScript SDK’en ved hjælp af Microsofts LibMan-værktøj, som håndterer klientbiblioteker på en måde der ligner NPM (Node Package Manager). SignalR SDK’en installeres derefter med kommandoen libman install @microsoft/signalr@latest -p unpkg -d wwwroot/js/signalr --files dist/browser/signalr.js.

Når vi har oprettet projektet og installeret SignalR SDK, er næste skridt at oprette og konfigurere Hub'en. Hub'en er afgørende for at etablere den nødvendige kommunikation mellem server og klient i realtid. For vores opgavestyringsapplikation skal vi oprette en Hub, der vil fungere som proxy for alle klienter, der tilsluttes serveren. Gennem Hub'en kan serveren eksekvere metoder på klienten og sende data, som opdaterer brugerens grænseflade i realtid.

Det er vigtigt at bemærke, at selvom SignalR letter kommunikationen i realtid, er det stadig nødvendigt at have en grundlæggende forståelse af webapplikationens komponenter og arkitektur. Serveren og klienten skal være korrekt konfigureret og kommunikationen skal opretholdes effektivt for at undgå problemer som f.eks. forbindelsestab eller langsomme opdateringer.

Der er også et væsentligt aspekt af performance, som bør overvejes, især når man arbejder med mange samtidige forbindelser. SignalR understøtter skalering af applikationen, så flere servere kan håndtere forbindelser på tværs af flere instanser. Det betyder, at du kan udvikle løsninger, der er skalerbare og kan håndtere en stor mængde brugere og data uden at gå på kompromis med realtidsfunktionaliteterne.

Når du arbejder med SignalR, bør du altid tage højde for de specifikke krav til dit system, herunder forbindelsens stabilitet, ydeevne og hvordan servere og klienter kommunikerer. At bruge SignalR på en effektiv måde kræver en grundig forståelse af netværkskommunikation og hvordan applikationens komponenter arbejder sammen.

Hvordan fungerer autentifikation og autorisation i moderne systemer?

Moderne systemer arbejder med identitetsstyring på forskellige niveauer. Som tidligere nævnt, kan webapplikationer sende anmodninger til forskellige API’er. API’er giver virksomheder mulighed for at tilbyde forretningstjenester, hvilket åbner op for mangfoldige integrationer mellem forskellige applikationer. Dette gør det muligt at have applikationer med forskellige funktionaliteter, som tilføjer værdi for brugeren, såsom kort-API’er, betalingsgateways og endda API’er, der tilbyder AI-funktioner. For at sikre, at applikationer og API’er kan kommunikere sikkert, er et identitetsbaseret sikkerhedsmekanisme nødvendigt. Med dette kan vi finde ud af, hvem der anmoder om information, og hvorfor de gør det. Denne sikkerhedsmekanisme opdeles i to begreber: autentifikation og autorisation.

Generelt ved vi, at denne tilgang involverer en login-flow. Dog er det væsentligt at forstå forskellen mellem autentifikation og autorisation.

Autentifikation

Autentifikation sigter mod at besvare spørgsmålet: "Hvem er du?" I autentifikations-flowet skal brugeren identificere sig selv ved hjælp af sine legitimationsoplysninger, såsom e-mail og adgangskode. Når disse oplysninger sendes til serveren ved at trykke på login-knappen, begynder applikationen at identificere brugeren ud fra de angivne legitimationsoplysninger. Hvis brugeren findes og godkendes i systemet, ved applikationen, hvem der forsøger at få adgang. Men dette er kun én del af processen. Når applikationen har identificeret brugeren, er det vigtigt at forstå, hvad denne bruger kan gøre. Dette håndteres i autorisationsprocessen.

Autorisation

Autorisation sigter mod at besvare spørgsmålet: "Hvad kan denne bruger gøre?" Efter at have identificeret brugeren, begynder applikationen at identificere brugerens rettigheder, som beskrevet i autorisations-flowet. Autorisation definerer det omfang, hvori brugeren kan handle, hvad enten det drejer sig om at administrere information eller få adgang til specifik data. Autorisations-flowet bruger ofte roller til at identificere brugeren, hvor det er muligt at gruppere adgangsniveauer inden for applikationens rammer. Rollen kan hjælpe med at definere de forskellige tilladelser, en bruger kan have. Dette er en meget anvendt metode, da det gør det lettere at administrere rettigheder på en systematisk måde.

Generelt set er autentifikations- og autorisationsprocesserne enkle, men for at kunne implementere dem på en sikker måde er der nogle standarder, vi bør være opmærksomme på: OAuth 2.0 og OpenID Connect (OIDC) protokollerne.

Forstå OAuth 2.0 og OIDC

Forestil dig en højsikkerhedsbygning. Her kan autorisation sammenlignes med at få tilladelse til at træde ind, mens autentifikation verificerer din identitet. OAuth 2.0 fokuserer på autorisation og giver brugere mulighed for at give adgang til deres data på en platform (såsom et socialt mediekonto) til en anden, uden at de behøver at dele deres faktiske adgangskoder. Med andre ord giver det os mulighed for at give andre applikationer adgang til visse oplysninger uden at afsløre vores legitimationsoplysninger. Dette ses ofte, når vi logger ind på en applikation med Microsoft-, Google-, Facebook-konti osv.

Den grundlæggende OAuth 2.0-flow kan defineres som følger:

  1. Brugeren logger ind på en ny applikation via deres sociale mediekonto.

  2. Applikationen omdirigerer brugeren til den sociale medieplatform (autoriseringsserveren).

  3. Efter login på den sociale mediekonto giver brugeren applikationen tilladelse til at bruge deres data (såsom navn, e-mail, profilbillede osv.).

  4. Autoriseringsserveren genererer specielle tokens for applikationen. Tokens bruges til at få adgang til brugerens data (adgangstokens). I nogle tilfælde bruges refresh tokens til at få nye tokens.

  5. Applikationen bruger adgangstokenet til at hente data fra den sociale medieplatform sikkert.

Dette flow muliggør, at applikationer kan udveksle oplysninger uden, at brugeren behøver at indtaste sine legitimationsoplysninger hver gang, hvilket øger både sikkerheden og bekvemmeligheden.

På den anden side bygger OpenID Connect (OIDC) oven på OAuth 2.0 og tilføjer et autentifikationslag. OIDC benytter OAuth-autoriseringsrammen til at bekræfte brugerens identitet via betroede udbydere som Google eller Facebook. Her er hvordan OIDC supplerer OAuth 2.0:

  1. Nogle applikationer tilbyder mulighed for at logge ind ved hjælp af sociale medieplatforme. I dette tilfælde bliver brugeren, under OAuth 2.0-flowet, omdirigeret til login-siden på deres sociale mediekonto (OpenID-udbyderen).

  2. Brugeren autentificerer sig med deres sociale mediekonto og bekræfter deres identitet.

  3. Med brugerens samtykke deler OpenID-udbyderen deres grundlæggende profilinformation (som navn og e-mail) med applikationen via et ID-token.

OIDC muliggør funktioner som single sign-on (SSO), hvilket gør det muligt at få adgang til flere applikationer med de samme loginoplysninger (for eksempel at logge ind på flere websteder med din Google-konto).

Selvom OAuth 2.0 og OIDC-flowet er lig, og de er tæt forbundne, har de forskellige formål:

  • Fokus: OAuth 2.0 handler om autorisation (adgang til data), mens OIDC beskæftiger sig med autentifikationslaget (bekræftelse af brugerens identitet).

  • Deling af information: OAuth 2.0 beskæftiger sig primært med adgangstokens, mens OIDC introducerer ID-tokens, der indeholder brugerens profiloplysninger.

Vi kan tænke på OAuth 2.0 som en nøgle, der åbner døren til et hus, mens OIDC bekræfter brugerens identitet, så denne nøgle kan gives. Dette flow er meget almindeligt i flere applikationer, som vi bruger dagligt.

Autorisation- og autentifikationsflows anvendes konstant af applikationer, hvilket giver dem mulighed for både at identificere, hvem brugerne er, og definere de tilladelser, som disse brugere har i et websystem eller API.

På trods af denne enkle forklaring på OAuth 2.0- og OIDC-protokollerne samt autorisation og autentifikation, er implementeringen af denne tilgang ikke simpel og afhænger af nogle vigtige mekanismer for at sikre, at funktionerne kører korrekt. ASP.NET Core 9 har abstraheringer, der understøtter udviklingen af identitetsstyring, mens de følger de standarder, der er blevet beskrevet. Abstraktionen, der implementerer disse ressourcer, kaldes ASP.NET Core Identity. Denne platform har udviklet sig med hver ny version og gør det muligt for udviklingsteam at anvende bedste praksis for sikkerhed i deres autorisations- og autentifikationsflows samt integrere med andre identitetsudbydere.

Hvad er vigtigt at forstå yderligere?

Når vi arbejder med autentifikations- og autorisationssystemer, er det vigtigt at forstå, at disse teknologier ikke blot handler om at sikre systemer mod uautoriseret adgang. De skaber også en brugeroplevelse, der er både sikker og bekvem. En god balance mellem disse aspekter kan forbedre applikationens brugeroplevelse og samtidig beskytte kritiske data og funktioner. Desuden er det nødvendigt at implementere robust fejlhåndtering og sikre, at sikkerhedsprotokoller og kryptering anvendes korrekt for at undgå potentielle sårbarheder. For udviklere er det afgørende at holde sig opdateret om de nyeste standarder og best practices, da autentifikations- og autorisationsmetoder konstant udvikler sig i takt med, at truslerne mod digitale systemer bliver mere komplekse.

Hvordan man opretter og konfigurerer en ASP.NET Core MVC-applikation

I denne sektion vil vi fortsætte med at oprette en webapplikation ved hjælp af MVC-skabelonen i ASP.NET Core. Først skal du køre følgende kommando:

bash
dotnet new mvc --name my-first-app

Denne kommando opretter en ny applikation baseret på MVC (Model-View-Controller) arkitekturmodellen. På dette tidspunkt behøver du ikke at bekymre dig om de tekniske detaljer bag MVC-mønsteret; vi vil dykke dybere ned i denne og andre emner som .NET CLI-værktøjer og projektmodeller gennem bogen.

Når applikationen er oprettet, skal du få adgang til den oprettede mappe med følgende kommando:

bash
cd my-first-app

Nu kan du åbne Visual Studio Code for at redigere kildeteksten i applikationen ved at bruge denne kommando:

bash
code .

Dette åbner Visual Studio Code i den oprettede mappe, hvor du kan begynde at foretage ændringer i koden.

I Visual Studio Code skal du finde index.cshtml-filen i mappen Views | Home. Åbn filen, og erstat linje 6 med følgende kode:

html
Welcome to ASP.NET Core 9!

Når du har gemt ændringerne (File > Save eller brug Ctrl + S), skal du vende tilbage til terminalen og køre applikationen med kommandoen:

bash
dotnet run

Hvis alt fungerer korrekt, bør du se en besked i terminalen, der indikerer, at applikationen kører. Du kan derefter åbne din browser og indtaste den adresse, der vises i terminalen (typisk noget som http://localhost:5034, men portnummeret kan variere). Hvis applikationen indlæses korrekt, betyder det, at din udviklingsmiljø er blevet korrekt konfigureret.

I tilfælde af problemer skal du gennemgå installationstrinnene for dit operativsystem og sikre, at både .NET SDK og din kodeeditor er korrekt konfigureret.

Hvad er nyt i ASP.NET Core 9?

ASP.NET Core 9, som er en del af .NET-platformen, har modtaget adskillige forbedringer og nye funktioner, som forbedrer udviklernes oplevelse og øger platformens performance. Nogle af de vigtigste forbedringer inkluderer:

  • Native AOT (Ahead of Time Compilation): Denne funktion blev introduceret i version 7.0 for at oprette selvstændige applikationer i en enkelt fil, som nu også understøtter x64- og ARM64-arkitekturer på macOS. Denne ændring har reduceret filstørrelsen betydeligt, især på Linux, med op til 50%.

  • Forbedringer i serialiseringsbiblioteker: .NET's egen System.Text.Json-API er blevet konstant opdateret og forbedret for at undgå afhængighed af tredjepartsbiblioteker og for at forbedre både performance og understøttelse af JSON.

  • Ydeevne: ASP.NET Core 9 har oplevet en samlet ydeevneforbedring på cirka 15%. Du kan finde flere detaljer om forbedringerne på Microsofts officielle dokumentationsside.

ASP.NET Core's løbende forbedringer gør det til en stærk og alsidig platform, der konstant tilpasser sig udviklernes behov. Det er også et resultat af den store støtte fra både Microsoft og open source-samfundet, som løbende opdaterer og udvider funktionaliteten.

Arbejdsmiljø og platformens fremtid

.NET-platformen, som er åben kildekode og uafhængig af operativsystem, har vundet stor popularitet på tværs af udviklingssamfundet. Denne platform understøtter ikke kun udvikling af webapplikationer men også desktop-løsninger, mobilapps og meget mere. Med forbedringer som de nævnte AOT-forbedringer og den forbedrede ydeevne forbliver .NET en af de mest kraftfulde teknologier til moderne applikationsudvikling.

.NET's vejledende roadmap, der opdateres af både Microsoft og samfundet, er et fremragende værktøj til at forstå, hvordan platformen udvikler sig. Den giver indsigt i de kommende funktioner og muligheder for udviklere.

Hvorfor vælge MVC?

MVC-modellen er en velkendt arkitektur, som adskiller en applikations data, brugergrænseflade og kontrollogik. Denne opdeling gør applikationen lettere at vedligeholde og udvide, hvilket er særligt vigtigt, når du arbejder på store projekter, der involverer flere udviklere. ASP.NET Core understøtter MVC og giver dig mulighed for at udvikle skalerbare og organiserede webapplikationer, hvor alle komponenter er klart adskilt. MVC er især effektivt, når du har brug for at bygge applikationer med komplekse brugerinteraktioner og server-side logik.

Vigtige aspekter ved ASP.NET Core 9

For at få det fulde udbytte af ASP.NET Core 9, er det vigtigt at forstå, hvordan de forskellige teknologier og frameworks kan arbejde sammen. ASP.NET Core understøtter flere metoder til at udvikle dynamiske web-applikationer, der inkluderer server-side rendering (som Razor Pages og MVC) og client-side rendering (som Blazor og JavaScript frameworks).

Denne fleksibilitet giver udviklere mulighed for at vælge den rette teknologi til den opgave, de står overfor, og kombinere flere til en hybridløsning, der udnytter både server- og klientkapabiliteter. At vælge den rette tilgang afhænger ofte af applikationens behov, brugerens interaktioner og de performancekrav, der stilles.

ASP.NET Core 9 giver ikke blot en solid arkitektur til udvikling af dynamiske webapplikationer, men også en platform, der er optimeret til at håndtere moderne krav som hastighed, skalerbarhed og brugervenlighed. Denne version tilbyder et væld af værktøjer og funktioner, som gør det nemmere at bygge, teste og implementere web-applikationer hurtigt og effektivt.

Hvordan konfigurerer man en CI/CD-pipeline med GitHub Actions?

I denne sektion lærer vi, hvordan man opretter og kører en CI/CD-pipeline ved hjælp af GitHub Actions, en integreret funktion til automatisering af udviklings- og distributionsprocesser. CI/CD, der står for kontinuerlig integration og kontinuerlig distribution, er en central praksis i DevOps, og det er et værktøj, der gør det muligt for udviklere at implementere ændringer hurtigt og pålideligt.

GitHub Actions giver udviklere mulighed for at bygge, teste og deployere applikationer automatisk, hvilket resulterer i hurtigere udviklingscyklusser og højere kodekvalitet. Denne proces begynder med oprettelsen af en workflow-fil, som definerer de specifikke handlinger, der skal udføres i pipeline. Vi gennemgår her, hvordan du konfigurerer en simpel pipeline til at bygge og publicere en Docker-container.

Når du opretter en GitHub Action, begynder du med at vælge at oprette en workflow selv. Som det vises i figur 10.24, klikker du på linket "set up a workflow yourself" og kommer til en editor, som giver dig mulighed for at definere pipeline-filen. Navnet på filen kan være noget som cicd-pipeline.yml, og du skal være opmærksom på den foreslåede katalogstruktur for at holde alt organiseret.

Indenfor editoren ser vi tre vigtige områder, som vi skal fokusere på: først er der den sektion, hvor filens navn kan defineres; herefter kommer det område, hvor vi skriver selve pipeline-koden; og til sidst er der en sektion, der indeholder "steps", eller de opgaver, som hver del af pipeline skal udføre. Koden til en simpel CI/CD pipeline kunne se sådan ud:

yaml
name: CI/CD Pipeline on: push: branches: - main jobs: build-and-deploy: name: Build and deploy runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/[email protected] - name: Build and publish Docker image run: | docker build -t ${{ secrets.DOCKER_HUB_USERNAME }}/urlshortener:latest . echo ${{ secrets.DOCKER_HUB_PASSWORD }} | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin docker push ${{ secrets.DOCKER_HUB_USERNAME }}/urlshortener:latest working-directory: ./Chapter-10/UrlShortener

Lad os gennemgå koden trin for trin. I første omgang definerer on-sektionen, hvordan og hvornår pipeline skal køres. I dette tilfælde vil det blive udløst hver gang der sker et push til main-grenen. jobs sektionen definerer den handling, der skal udføres. Jobs er en samling af operationer, der udføres i rækkefølge. Hver job kan bestå af flere "steps", som er de specifikke handlinger, der udføres.

I dette tilfælde er der to steps: det første checkout, som sørger for at hente kildekoden fra repository, og det andet step, hvor Docker-billedet bliver bygget og offentliggjort på Docker Hub. Docker kommandoerne, som bygger og logger ind på Docker Hub, bruger hemmelige nøgler (som Docker Hub brugernavn og adgangskode), hvilket sikrer, at følsomme oplysninger ikke bliver afsløret i pipeline-loggen.

Det er vigtigt at forstå YAML-filens struktur, som er afhængig af korrekt brug af indrykninger med mellemrum for at oprette den ønskede hierarkiske opbygning. Hvis strukturen ikke respekteres, vil pipeline ikke køre korrekt. For eksempel skal vi bruge to mellemrum for at indrykke elementer som branches og steps.

Når koden er skrevet, kan vi gemme ændringerne og forpligte filen til GitHub. Når du klikker på "Commit Changes", vil denne handling udløse pipeline, og GitHub Actions vil begynde at bygge og deployere Docker-billedet.

En vigtig funktion ved GitHub Actions er dens evne til at automatisere de gentagne opgaver i udviklings- og deploymentsprocessen, hvilket reducerer manuel indsats og risiko for fejl. Når pipeline er i gang, kan du se dens fremskridt under "Actions"-fanen på GitHub, og når den er færdig, kan du kontrollere, at den nye Docker-container er blevet uploadet til Docker Hub.

GitHub Actions giver teams mulighed for at reagere hurtigt på ændringer i koden og sikrer, at applikationen altid er opdateret og tilgængelig. Denne automatisering af CI/CD-processen er central i DevOps-kulturen, hvor kontinuerlig integration og kontinuerlig levering er fundamentale for effektiv softwareudvikling.

En anden vigtig overvejelse er, at når du arbejder med GitHub Actions og Docker, er det nødvendigt at forstå, hvordan man håndterer hemmelige data som brugernavne og adgangskoder på en sikker måde. GitHub Actions giver mulighed for at bruge "Secrets" til at gemme disse oplysninger sikkert, og dette er en praktisk metode til at beskytte dine adgangsoplysninger, når du bygger og deployerer Docker-containere. Det er også vigtigt at holde øje med pipeline-loggene for at sikre, at alt kører som forventet.

Med denne pipeline oprettet og kørt, kan du nu være sikker på, at enhver ændring, der bliver lavet og commit'et til dit repository, automatisk vil føre til en ny version af din Docker-container. Det betyder, at du altid har en opdateret version af din applikation kørende, hvilket er en af de største fordele ved CI/CD-arbejdsgange.