Sdílet prostřednictvím


Sdílení certifikátů mezi aplikacemi pro Windows

Aplikace pro Windows, které vyžadují zabezpečené ověřování nad rámec kombinace ID uživatele a hesla, můžou k ověřování používat certifikáty. Ověřování certifikátů poskytuje vysokou úroveň důvěryhodnosti při ověřování uživatele. V některých případech bude skupina služeb chtít ověřit uživatele pro více aplikací. V tomto článku se dozvíte, jak můžete ověřit více aplikací pro Windows pomocí stejného certifikátu a jak můžete uživatelům poskytnout metodu importu certifikátu poskytnutého pro access do zabezpečených webových služeb.

Aplikace se můžou ověřit ve webové službě pomocí certifikátu a více aplikací může k ověření stejného uživatele použít jeden certifikát z úložiště certifikátů. Pokud certifikát v úložišti neexistuje, můžete do aplikace přidat kód pro import certifikátu ze souboru PFX. Klientská aplikace v tomto rychlém úvodu je aplikace WinUI 3 a webová služba je ASP.NET Core webové API.

Návod

Microsoft Copilot je skvělým prostředkem, pokud máte dotazy ohledně začátků s psaním aplikací pro Windows nebo webových rozhraní API v ASP.NET Core. Copilot vám může pomoct s psaním kódu, hledáním příkladů a dalšími informacemi o osvědčených postupech pro vytváření zabezpečených aplikací.

Požadavky

Vytvoření a publikování zabezpečené webové služby

  1. Otevřete Microsoft Visual Studio a na úvodní obrazovce vyberte Vytvořit nový project.

  2. V dialogovém okně Vytvořit nový projekt vyberte API v rozevíracím seznamu Vyberte typ projektu pro filtrování dostupných šablon projektů.

  3. Vyberte šablonu webového rozhraní API ASP.NET Core a vyberte Dalši.

  4. Pojmenujte aplikaci FirstContosoBank a vyberte Další.

  5. Zvolte .NET 8.0 nebo novější jako Framework, nastavte typ autentizace na None, ujistěte se, že je zaškrtnuté políčko Konfigurace pro HTTPS, zrušte zaškrtnutí Povolit podporu OpenAPI, zkontrolujte, Nepoužívat příkazy nejvyšší úrovně a Použít kontrolery, a vyberte Vytvořit.

    Snímek obrazovky z Visual Studio s podrobnostmi o vytvoření nového projektu webového rozhraní ASP.NET Core

  6. Klikněte pravým tlačítkem myši na soubor WeatherForecastController.cs ve složce Kontrolery a vyberte Přejmenovat. Změňte název na BankController.cs a nechte Visual Studio přejmenovat třídu a všechny odkazy na třídu.

  7. V souborulaunchSettings.json změňte hodnotu launchUrl z "weatherforecast" na "bank" pro všechny tři konfigurace, která hodnotu používá.

  8. Do souboru BankController.cs přidejte následující metodu Login.

    [HttpGet]
    [Route("login")]
    public string Login()
    {
        // Return any value you like here.
        // The client is just looking for a 200 OK response.
        return "true";
    }
    
  9. Otevřete Package Manager NuGet a vyhledejte a nainstalujte nejnovější stabilní verzi balíčku Microsoft.AspNetCore.Authentication.Certificate. Tento balíček poskytuje middleware pro ověřování certifikátů v ASP.NET Core.

  10. Přidejte novou třídu do project s názvem SecureCertificateValidationService. Přidejte do třídy následující kód pro konfiguraci middlewaru ověřování certifikátů.

    using System.Security.Cryptography.X509Certificates;
    
    public class SecureCertificateValidationService
    {
        public bool ValidateCertificate(X509Certificate2 clientCertificate)
        {
            // Values are hard-coded for this example.
            // You should load your valid thumbprints from a secure location.
            string[] allowedThumbprints = { "YOUR_CERTIFICATE_THUMBPRINT_1", "YOUR_CERTIFICATE_THUMBPRINT_2" };
            if (allowedThumbprints.Contains(clientCertificate.Thumbprint))
            {
                return true;
            }
        }
    }
    
  11. Otevřete Program.cs a nahraďte kód v metodě Main následujícím kódem:

    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
    
        // Add our certificate validation service to the DI container.
        builder.Services.AddTransient<SecureCertificateValidationService>();
    
        builder.Services.Configure<KestrelServerOptions>(options =>
        {
            // Configure Kestrel to require a client certificate.
            options.ConfigureHttpsDefaults(options =>
            {
                options.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
                options.AllowAnyClientCertificate();
            });
        });
    
        builder.Services.AddControllers();
    
        // Add certificate authentication middleware.
        builder.Services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
           .AddCertificate(options =>
        {
            options.AllowedCertificateTypes = CertificateTypes.SelfSigned;
            options.Events = new CertificateAuthenticationEvents
            {
                // Validate the certificate with the validation service.
                OnCertificateValidated = context =>
                {
                    var validationService = context.HttpContext.RequestServices.GetService<SecureCertificateValidationService>();
    
                    if (validationService.ValidateCertificate(context.ClientCertificate))
                    {
                        context.Success();
                    }
                    else
                    {
                        context.Fail("Invalid certificate");
                    }
    
                    return Task.CompletedTask;
                },
                OnAuthenticationFailed = context =>
                {
                    context.Fail("Invalid certificate");
                    return Task.CompletedTask;
                }
            };
         });
    
         var app = builder.Build();
    
         // Add authentication/authorization middleware.
         app.UseHttpsRedirection();
         app.UseAuthentication();
         app.UseAuthorization();
    
         app.MapControllers();
         app.Run();
     }
    

    Výše uvedený kód nakonfiguruje server Kestrel tak, aby vyžadoval klientský certifikát a přidal do aplikace middleware pro ověřování certifikátů. Middleware ověří klientský certifikát pomocí SecureCertificateValidationService třídy. Událost OnCertificateValidated se volá při ověření certifikátu. Pokud je certifikát platný, událost volá metodu Success . Pokud je certifikát neplatný, událost volá metodu Fail s chybovou zprávou, která se vrátí klientovi.

  12. Začněte ladit projekt, aby se spustila webová služba. Můžete dostávat zprávy o důvěryhodnosti a instalaci certifikátu SSL. Klikněte na Ano pro každou z těchto zpráv, abyste certifikátu důvěřovali, a pokračujte v ladění projektu.

    Snímek obrazovky s dialogovým oknem s dotazem uživatele, jestli chce důvěřovat certifikátu

    Snímek obrazovky s dialogovým oknem Windows s dotazem uživatele, jestli chce nainstalovat certifikát

  13. Webová služba bude k dispozici na adrese https://localhost:7072/bank. Webovou službu můžete otestovat tak, že otevřete webový prohlížeč a zadáte webovou adresu. Zobrazí se vygenerovaná data předpovědi počasí formátovaná jako JSON. Během vytváření klientské aplikace nechte webovou službu spuštěnou.

Další informace o práci s webovými rozhraními API založenými na kontroleru ASP.NET Core najdete v tématu Vytvoření webového rozhraní API pomocí ASP.NET Core.

Vytvoření aplikace WinUI, která používá ověřování certifikátů

Teď, když máte jednu nebo více zabezpečených webových služeb, můžou vaše aplikace k ověření těchto webových služeb použít certifikáty. Když odešlete požadavek na ověřenou webovou službu pomocí objektu HttpClient z rozhraní API WinRT, počáteční požadavek nebude obsahovat klientský certifikát. Ověřená webová služba odpoví žádostí o ověření klienta. Když k tomu dojde, klient Systému Windows automaticky odešle dotaz na úložiště certifikátů pro dostupné klientské certifikáty. Uživatel si může vybrat z těchto certifikátů, aby se ověřil ve webové službě. Některé certifikáty jsou chráněné heslem, takže budete muset uživateli poskytnout způsob, jak zadat heslo pro certifikát.

Poznámka:

Pro správu certifikátů zatím neexistují žádná rozhraní API Windows App SDK. Ke správě certifikátů v aplikaci musíte použít rozhraní API WinRT. K importu certifikátu ze souboru PFX použijeme také rozhraní API winRT storage. Mnoho rozhraní API WinRT může používat libovolná aplikace Windows s identitou balíčku, včetně aplikací WinUI.

Kód klienta HTTP, který budeme implementovat, používá .NET HttpClient. HttpClient zahrnutý v rozhraních API WinRT nepodporuje klientské certifikáty.

Pokud nejsou k dispozici žádné klientské certifikáty, uživatel bude muset přidat certifikát do úložiště certifikátů. Do aplikace můžete zahrnout kód, který uživateli umožní vybrat soubor PFX, který obsahuje klientský certifikát, a pak tento certifikát importovat do úložiště klientských certifikátů.

Návod

Pomocí rutin PowerShellu New-SelfSignedCertificate a Export-PfxCertificate můžete vytvořit certifikát podepsaný svým držitelem a exportovat ho do souboru PFX, který se použije v tomto rychlém startu. Pro více informací se podívejte na New-SelfSignedCertificate a Export-PfxCertificate.

Všimněte si, že při generování certifikátu byste měli uložit kryptografický otisk certifikátu, který se má použít ve webové službě k ověření.

  1. Otevřete Visual Studio a na úvodní stránce vytvořte nový project WinUI. Pojmenujte nový projekt "FirstContosoBankApp". Kliknutím na Create vytvořte nový project.

  2. V souboru MainWindow.xaml přidejte následující XAML do Element Gridu a nahraďte existující StackPanel element a jeho obsah. Tento KÓD XAML obsahuje tlačítko pro vyhledání souboru PFX pro import, textové pole pro zadání hesla pro soubor PFX chráněného heslem, tlačítko pro import vybraného souboru PFX, tlačítko pro přihlášení k zabezpečené webové službě a blok textu pro zobrazení stavu aktuální akce.

    <Button x:Name="Import" Content="Import Certificate (PFX file)" HorizontalAlignment="Left" Margin="352,305,0,0" VerticalAlignment="Top" Height="77" Width="260" Click="Import_Click" FontSize="16"/>
    <Button x:Name="Login" Content="Login" HorizontalAlignment="Left" Margin="611,305,0,0" VerticalAlignment="Top" Height="75" Width="240" Click="Login_Click" FontSize="16"/>
    <TextBlock x:Name="Result" HorizontalAlignment="Left" Margin="355,398,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="153" Width="560"/>
    <PasswordBox x:Name="PfxPassword" HorizontalAlignment="Left" Margin="483,271,0,0" VerticalAlignment="Top" Width="229"/>
    <TextBlock HorizontalAlignment="Left" Margin="355,271,0,0" TextWrapping="Wrap" Text="PFX password" VerticalAlignment="Top" FontSize="18" Height="32" Width="123"/>
    <Button x:Name="Browse" Content="Browse for PFX file" HorizontalAlignment="Left" Margin="352,189,0,0" VerticalAlignment="Top" Click="Browse_Click" Width="499" Height="68" FontSize="16"/>
    <TextBlock HorizontalAlignment="Left" Margin="717,271,0,0" TextWrapping="Wrap" Text="(Optional)" VerticalAlignment="Top" Height="32" Width="83" FontSize="16"/>
    
  3. Uložte změny MainWindow .

  4. Otevřete soubor MainWindow.xaml.cs a přidejte následující using příkazy.

    using System;
    using System.Security.Cryptography.X509Certificates;
    using System.Diagnostics;
    using System.Net.Http;
    using System.Net;
    using System.Text;
    using Microsoft.UI.Xaml;
    using Windows.Security.Cryptography.Certificates;
    using Windows.Storage.Pickers;
    using Windows.Storage;
    using Windows.Storage.Streams;
    
  5. Do souboru MainWindow.xaml.cs přidejte do třídy MainWindow následující proměnné. Zadají adresu pro koncový bod zabezpečené přihlašovací služby vaší webové služby FirstContosoBank a globální proměnnou, která obsahuje certifikát PFX pro import do úložiště certifikátů. Aktualizujte <server-name> na localhost:7072 nebo na jiný port uvedený v konfiguraci "https" v souboru launchSettings.json projektu vašeho API.

    private Uri requestUri = new Uri("https://<server-name>/bank/login");
    private string pfxCert = null;
    
  6. Do souboru MainWindow.xaml.cs přidejte následující obslužný program kliknutí pro tlačítko přihlášení a metodu pro přístup k zabezpečené webové službě.

    private void Login_Click(object sender, RoutedEventArgs e)
    {
        MakeHttpsCall();
    }
    
    private async void MakeHttpsCall()
    {
        var result = new StringBuilder("Login ");
    
        // Load the certificate
        var certificate = new X509Certificate2(Convert.FromBase64String(pfxCert),
                                               PfxPassword.Password);
    
        // Create HttpClientHandler and add the certificate
        var handler = new HttpClientHandler();
        handler.ClientCertificates.Add(certificate);
        handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
    
        // Create HttpClient with the handler
        var client = new HttpClient(handler);
    
        try
        {
            // Make a request
            var response = await client.GetAsync(requestUri);
    
            if (response.StatusCode == HttpStatusCode.OK)
            {
                result.Append("successful");
            }
            else
            {
                result = result.Append("failed with ");
                result = result.Append(response.StatusCode);
            }
        }
        catch (Exception ex)
        {
            result = result.Append("failed with ");
            result = result.Append(ex.Message);
        }
    
        Result.Text = result.ToString();
    }
    
  7. Dále přidejte následující obslužné rutiny kliknutí pro tlačítko pro vyhledání souboru PFX a tlačítko pro import vybraného souboru PFX do úložiště certifikátů.

    private async void Import_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            Result.Text = "Importing selected certificate into user certificate store....";
            await CertificateEnrollmentManager.UserCertificateEnrollmentManager.ImportPfxDataAsync(
                  pfxCert,
                  PfxPassword.Password,
                  ExportOption.Exportable,
                  KeyProtectionLevel.NoConsent,
                  InstallOptions.DeleteExpired,
                  "Import Pfx");
    
            Result.Text = "Certificate import succeeded";
        }
        catch (Exception ex)
        {
            Result.Text = "Certificate import failed with " + ex.Message;
        }
    }
    
    private async void Browse_Click(object sender, RoutedEventArgs e)
    {
        var result = new StringBuilder("Pfx file selection ");
        var pfxFilePicker = new FileOpenPicker();
        IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
        WinRT.Interop.InitializeWithWindow.Initialize(pfxFilePicker, hwnd);
        pfxFilePicker.FileTypeFilter.Add(".pfx");
        pfxFilePicker.CommitButtonText = "Open";
        try
        {
            StorageFile pfxFile = await pfxFilePicker.PickSingleFileAsync();
            if (pfxFile != null)
            {
                IBuffer buffer = await FileIO.ReadBufferAsync(pfxFile);
                using (DataReader dataReader = DataReader.FromBuffer(buffer))
                {
                    byte[] bytes = new byte[buffer.Length];
                    dataReader.ReadBytes(bytes);
                    pfxCert = System.Convert.ToBase64String(bytes);
                    PfxPassword.Password = string.Empty;
                    result.Append("succeeded");
                }
            }
            else
            {
                result.Append("failed");
            }
        }
        catch (Exception ex)
        {
            result.Append("failed with ");
            result.Append(ex.Message); ;
        }
    
        Result.Text = result.ToString();
    }
    
  8. Otevřete soubor Package.appxmanifest a na kartu Schopnosti přidejte následující možnosti.

    • EnterpriseAuthentication (Podnikové ověřování)
    • Sdílené uživatelské certifikáty
  9. Spusťte aplikaci a přihlaste se k zabezpečené webové službě a naimportujte soubor PFX do místního úložiště certifikátů.

    Snímek obrazovky aplikace WinUI s tlačítky pro vyhledání souboru PFX, import certifikátu a přihlášení k zabezpečené webové službě

Pomocí těchto kroků můžete vytvořit více aplikací, které používají stejný uživatelský certifikát k access stejných nebo různých zabezpečených webových služeb.

Windows Hello

Zabezpečení a identita

Vytvoření webového rozhraní API pomocí ASP.NET Core