At publicere en Azure Functions-app kræver nøje opmærksomhed på bygge- og deploymentsprocessen, hvor Visual Studio eller Visual Studio Code ofte benyttes som værktøjer til at udvikle og implementere applikationen. Under build-processen bliver projektet kompilering med henblik på release-konfiguration, hvor outputtet kontrolleres for eventuelle fejl eller advarsler. Det er vigtigt at være opmærksom på beskeder omkring versioner, eksempelvis advarsler om brug af preview-versioner af .NET, da disse kan have indflydelse på stabiliteten og supportmulighederne i produktion.

Når byggeriet er gennemført, følger selve publiceringen til Azure-platformen. Dette involverer typisk en zip-deployment, hvor de nødvendige filer pakkes og sendes til Azure via en API-endpoint. Efter deployment overvåges output-vinduet for at bekræfte succesfuld upload og at funktionen er klar til brug. Når tjenesten er klar, kan den testes direkte via en browser ved at tilføje en funktionens relativ URL til basisadressen, hvilket gør det nemt at validere funktionaliteten i cloud-miljøet.

Brugen af Visual Studio Code til publicering kræver login til Azure og kan integreres gennem dokumentation og vejledninger, der støtter udvikleren i at håndtere autentificering, konfiguration og fejlhåndtering i deploymentsprocessen.

Ressourcestyring er et andet vigtigt aspekt, hvor det er nødvendigt at forstå, hvordan man effektivt kan rydde op i Azure-ressourcer for at undgå unødvendige omkostninger. En samlet ressourcegruppe, der indeholder alle relevante komponenter som Storage Accounts, Function Apps og App Service-planer, kan nemt slettes samlet via Azure-portalen. Alternativt kan individuelle ressourcer fjernes, men samlet sletning er ofte mere effektiv.

Det er væsentligt at forstå forskellen mellem forskellige hostingmodeller for Azure Functions, såsom in-process versus isolated hosting, da denne påvirker ydelse, sikkerhed og udviklingsfleksibilitet. Triggere, som styrer hvornår og hvordan funktioner aktiveres, benytter attributter der knytter sig til fx køer eller tidsplaner, hvilket muliggør forskellige integrationsscenarier, herunder håndtering af asynkrone beskeder eller periodiske opgaver.

Endvidere er afhængighedsinjektion en central mekanisme til konfiguration af services i funktionerne, hvilket tillader løs kobling og bedre testbarhed. Det er også vigtigt at kunne læse og forstå tidsplaner udtrykt i NCRONTAB format for at kunne definere kørselstidspunkter præcist.

Det er ikke nok blot at følge trin for trin i deployment-processen; en dybere forståelse af de underliggende koncepter omkring Azure Functions og serverless arkitektur sikrer, at udvikleren kan udnytte platformens fulde potentiale. At kunne navigere i og administrere ressourcer effektivt, at forstå funktionslivscyklussen og trigger-arkitekturen, samt at kunne implementere sikker og skalerbar kode er afgørende kompetencer. Endvidere bør læseren være opmærksom på, at serverless ikke altid betyder gratis eller ubegrænset; omkostningsstyring og performance-monitorering skal derfor indgå som en naturlig del af driften.

Hvordan integrere .NET MAUI-apps med Blazor og native platforme

For udviklere, der arbejder med .NET MAUI (Multi-platform App UI), er integrationen af native platforme og webbaserede teknologier som Blazor en vigtig del af at skabe effektive, tværplatforms apps. Dette kapitel giver en praktisk fremstilling af, hvordan man kan integrere .NET MAUI-applikationer med Blazor og samtidig udnytte native platformfunktioner.

Når du starter med at udvikle en .NET MAUI-app, skal du først oprette og køre de nødvendige projekter. Et praktisk eksempel på dette er at starte Northwind.Maui.WebApi.Service projektet med https-profilen og notere de endepunkter, som det lytter på, som vist i terminaloutput. Dette danner grundlaget for den efterfølgende webservice-integration. Når tjenesten er startet, vil du kunne se de specifikke URL’er, der bliver brugt til at kommunikere med applikationen.

I et andet eksempel, når du kører Northwind.Maui.Blazor.Client projektet på en Android-emulator, vil du kunne navigere til kategorisiden, hvor otte kategorier bliver hentet fra webservicen og vises i et karussel-layout. Her er det muligt for brugeren at swipe til venstre og højre for at navigere mellem kategorierne, eller bruge indikatorerne nederst for hurtigt at hoppe til den ønskede kategori.

Det er en enkel, men kraftfuld funktionalitet, der demonstrerer, hvordan man kan udnytte Blazor-komponenter sammen med native platformer. Denne funktionalitet er ikke kun begrænset til Android; ved at køre projektet på en Windows-maskine får man en identisk oplevelse med mulighed for at bruge den horisontale scrollbar til at navigere gennem kategorierne.

I .NET MAUI tilbyder platformen tværplatforms-API’er, der muliggør adgang til native enhedsfunktioner. Dette inkluderer blandt andet:

  • Arbejde med systemets udklipsholder

  • Hente filer og medier fra det lokale filsystem

  • Sikre opbevaring af data i en lokal ordbog (key-value storage)

  • Indhente information om enhedens operativsystemversion

  • Læse sensordata som accelerometer eller kompas

  • Kontrollere netværksforbindelse

  • Benytte native brugergrænseflade-interaktioner som menuer og toast-beskeder

En af de mest almindelige anvendelser af native funktioner er integration med udklipsholderen. For eksempel kan en bruger under redigering af en kategori ønsker at kopiere en beskrivelse fra et andet program, som en tekstbehandler eller notesapp. I sådanne tilfælde bliver udklipsholderintegration en essentiel funktionalitet. Det er dog kun tekst, der kan integreres.

For at aktivere integrationen med udklipsholderen i en MAUI-app, kan du følge denne fremgangsmåde:

  1. I EmployeesPage.xaml ændrer du titlen, justerer den lodrette afstand i stakken og erstatter den eksisterende label med en frame, en entry og et par knapper til at kopiere og indsætte tekst fra og til udklipsholderen.

  2. I EmployeesPage.xaml.cs tilføjes metoder i eventhandlerne for knapperne, som kalder de standard metoder for at sætte og hente tekst fra udklipsholderen, som vist i koden:

    csharp
    namespace Northwind.Maui.Blazor.Client.Views;
    public partial class EmployeesPage : ContentPage
    {
    public EmployeesPage() { InitializeComponent(); } private async void CopyToClipboardButton_Clicked(object sender, EventArgs e) { await Clipboard.Default.SetTextAsync(NotesTextBox.Text); } private async void PasteFromClipboardButton_Clicked(object sender, EventArgs e) { if (Clipboard.HasText) { NotesTextBox.Text = await Clipboard.Default.GetTextAsync(); } } }
  3. Start projektet i Android-emulatoren og naviger til Employees-siden.

  4. Indtast noget tekst i entry-boksen, for eksempel "Hello, Clipboard!".

  5. Klik på knappen "Copy to Clipboard".

  6. Start Notepad på Windows (Android-emulatoren integrerer automatisk med Windows-udklipsholderen).

  7. Indsæt teksten, og du vil bemærke, at den tekst, du skrev i entry-boksen, nu vises i Notepad.

Ved at bruge denne funktionalitet kan applikationen udnytte native platformfunktioner til at håndtere tekstindhold på tværs af enheder og platforme, hvilket forbedrer brugeroplevelsen ved at gøre det lettere at arbejde med eksterne data og apps.

Det er også værd at bemærke, at integrationen af native platformfunktioner som udklipsholderen ikke er begrænset til én enhedstype. Den samme funktionalitet vil virke på både Android og Windows, hvilket gør det muligt at opbygge apps, der fungerer problemfrit på tværs af platforme. Denne tilgang styrker muligheden for at bygge mere komplekse, tværplatforms apps, der udnytter både native funktioner og webteknologier som Blazor.

Desuden er det vigtigt at forstå, at .NET MAUI ikke kun er et værktøj til at bygge apps, men også en bro mellem native funktioner og webbaserede teknologier. Med denne platform kan udviklere integrere Blazor-komponenter og samtidig udnytte de muligheder, som native funktioner tilbyder, hvilket skaber en mere robust og alsidig appoplevelse. Når man arbejder med .NET MAUI, bør man altid tænke på den dobbelte tilgang: hvordan man kan udnytte både native funktionalitet og webteknologier for at skabe den bedste brugeroplevelse.

Hvordan opbygger man sikre webtjenester med Minimal APIs og JWT-autorisation?

I denne artikel ser vi på, hvordan man kan opbygge en webtjeneste ved hjælp af Minimal APIs i ASP.NET Core, som både er let at implementere og effektiv i sin håndtering af autorisation gennem JWT (JSON Web Tokens). Vi gennemgår, hvordan man beskytter bestemte API-ruter ved hjælp af JWT-baseret autorisation, og hvordan man håndterer autentifikation af brugere gennem webtjenester.

Når man arbejder med webtjenester, er sikkerhed et grundlæggende aspekt, og det er vigtigt at kunne autentificere brugere for at sikre, at kun autoriserede brugere kan få adgang til følsomme oplysninger. Dette opnås ved at kræve en Bearer-token i HTTP-anmodninger for at validere, om en bruger er godkendt. I den følgende implementering vil vi se på, hvordan man kan sikre en rute, der returnerer en hemmelig ingrediens, som kun autoriserede brugere kan få adgang til.

I ASP.NET Core kan vi nemt oprette sådanne API'er ved at anvende MapGet() til at definere ruter. En grundlæggende rute kan se sådan ud:

csharp
app.MapGet("/", () => "Hello World!")
.ExcludeFromDescription();

Denne kode opretter en simpel GET-anmodning, som returnerer "Hello World!". For at beskytte en rute, såsom /secret, som kun skal være tilgængelig for godkendte brugere, kan vi tilføje en autorisationskrav til ruten:

csharp
app.MapGet("/secret", (ClaimsPrincipal user) => $"Welcome, {user.Identity?.Name ?? "secure user"}. The secret ingredient is love.") .RequireAuthorization();

Her anvender vi RequireAuthorization() for at sikre, at kun brugere, der er korrekt autentificeret, kan få adgang til den hemmelige besked. Hvis brugeren ikke er autoriseret, vil de få en 401 Unauthorized fejl.

Når det kommer til at generere en JWT-token for brugere, kan vi bruge kommandoen dotnet user-jwts create, som skaber en JWT for den bruger, vi ønsker at autentificere. Det resulterende token vil være nødvendigt for at få adgang til de beskyttede ruter. Du kan eksempelvis generere en JWT som følger:

bash
dotnet user-jwts create

Når token er oprettet, kan du hente dets detaljer ved hjælp af kommandoen dotnet user-jwts print <id> --show-all, som viser dig metadata om tokenet, såsom dets udløbstidspunkt, målgruppe (audience), og tokenets strukturelle opbygning i form af Base64-kodede sektioner.

I din appsettings.Development.json kan du definere en sektion for autentifikation, der specificerer hvilke udbydere og domæner der er gyldige. Et eksempel på konfiguration kunne se sådan ud:

json
"Authentication": { "Schemes": { "Bearer": { "ValidAudiences": [ "http://localhost:30225", "https://localhost:44344" ], "ValidIssuer": "dotnet-user-jwts" } } }

Dette konfigurerer, at kun anmodninger fra disse validerede domæner og udbydere vil blive accepteret.

Når du har konfigureret din applikation, kan du teste adgangen til den beskyttede rute. Hvis du forsøger at tilgå /secret uden et gyldigt token, vil du få en 401 Unauthorized fejl. Derimod, hvis du sender et GET-anmodning med en Bearer-token som en del af autorisationshovedet, som vist her:

http
GET https://localhost:5091/secret/ Authorization: Bearer <din_token>

så vil du få en succesfuld respons med en besked som: "Welcome, secure user. The secret ingredient is love."

Denne implementering sikrer, at kun godkendte brugere, som har et gyldigt JWT-token, kan få adgang til beskyttede ressourcer i webtjenesten. Det er en simpel, men effektiv metode til at implementere autentifikation og autorisation i Minimal APIs.

Det er også vigtigt at forstå, hvordan JWT-token fungerer. Tokenet består af tre dele: header, payload og signatur. Headeren definerer hvilken algoritme der anvendes til at signere tokenet (f.eks. HMACSHA256), mens payloaden indeholder brugerens oplysninger og metadata. Signaturen bruges til at sikre, at tokenet ikke er blevet manipuleret.

Desuden bør du være opmærksom på, at JWT-token kan udløbe. Som standard udløber tokens efter tre måneder, men dette kan konfigureres i din applikation. Du skal være opmærksom på, hvordan du håndterer udløbne tokens og implementerer en mekanisme for at genforny dem, hvis det er nødvendigt.

En yderligere vigtig overvejelse er, at CORS (Cross-Origin Resource Sharing) kan spille en rolle i sikkerheden af din webtjeneste, især hvis den skal være tilgængelig fra forskellige domæner. CORS tillader dig at kontrollere, hvilke domæner der må lave anmodninger til din tjeneste, hvilket kan beskytte din API mod ondsindede websteder.

En effektiv rate-limiting mekanisme er også vigtig for at forhindre DDoS-angreb (Denial of Service), hvor angriberen forsøger at overbelaste serveren med et stort antal anmodninger. Der findes flere pakker i ASP.NET Core, som kan hjælpe med at begrænse antallet af anmodninger pr. klient eller pr. endpoint.

Denne tilgang til sikker webtjenesteudvikling med Minimal APIs og JWT-baseret autorisation gør det muligt for udviklere at bygge sikre og skalerbare applikationer, der effektivt kan beskytte følsomme data.