Tanúsítványok megosztása Windows-alkalmazások között

A felhasználóazonosítón és jelszókombináción túl biztonságos hitelesítést igénylő Windows-alkalmazások tanúsítványokat használhatnak a hitelesítéshez. A tanúsítványhitelesítés magas szintű megbízhatóságot biztosít a felhasználók hitelesítése során. Bizonyos esetekben egy szolgáltatáscsoport több alkalmazáshoz is hitelesíteni szeretné a felhasználót. Ez a cikk bemutatja, hogyan hitelesíthet több Windows-alkalmazást ugyanazzal a tanúsítvánnyal, és hogyan biztosíthatja azt a módszert, amellyel a felhasználók importálhatják az access által biztosított tanúsítványt a biztonságos webszolgáltatásokhoz.

Az alkalmazások tanúsítvány használatával hitelesíthetik magukat egy webszolgáltatásban, és több alkalmazás is használhat egyetlen tanúsítványt a tanúsítványtárból ugyanazon felhasználó hitelesítéséhez. Ha egy tanúsítvány nem létezik az áruházban, hozzáadhat kódot az alkalmazáshoz, hogy egy tanúsítványt PFX-fájlból importáljon. A rövid útmutatóban szereplő ügyfélalkalmazás egy WinUI 3-alkalmazás, a webszolgáltatás pedig egy ASP.NET Core webes API.

Jótanács

Microsoft Copilot nagyszerű erőforrás, ha kérdései vannak a Windows-alkalmazások vagy az ASP.NET Core webes API-k írásának megkezdéséről. A Copilot segíthet a kódírásban, példák keresésében és a biztonságos alkalmazások létrehozásának ajánlott eljárásaiban.

Előfeltételek

Biztonságos webszolgáltatás létrehozása és közzététele

  1. Nyissa meg a Microsoft Visual Studio, és válassza a Új project létrehozása a kezdőképernyőn.

  2. Az új project létrehozása párbeszédpanelen válassza a API lehetőséget a Válasszon ki egy project típust legördülő listát az elérhető project sablonok szűréséhez.

  3. Válassza ki a ASP.NET Core Webes API sablont, és válassza a Next lehetőséget.

  4. Nevezze el az alkalmazásnak a "FirstContosoBank" nevet, és válassza a Tovább gombot.

  5. Válassza a .NET 8.0 vagy újabb verziót a Framework, állítsa a hitelesítés típusátNone értékre, győződjön meg arról, hogy a HTTPS konfiguráció be van jelölve, törölje a jelölést az Enable OpenAPI-támogatás opcióról, jelölje be a Ne használjon legfelső szintű utasításokat és a Vezérlők opciókat, és válassza a Create lehetőséget.

    Egy képernyőkép a Visual Studio ASP.NET Core webes API projekt létrehozásának részleteiről

  6. Kattintson a jobb gombbal a WeatherForecastController.cs fájlra a Vezérlők mappában, és válassza az Átnevezés lehetőséget. Módosítsa a nevet BankController.cs, és hagyja, hogy Visual Studio nevezze át az osztályt és az osztályra mutató összes hivatkozást.

  7. A launchSettings.json fájlban módosítsa a "launchUrl" értékét a "weatherforecast" értékről "bank" értékre mind a három konfiguráció esetében, amely az értéket használja.

  8. A BankController.cs fájlban adja hozzá a következő "Login" metódust.

    [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. Nyissa meg a NuGet-Package Manager, és keresse meg és telepítse a Microsoft.AspNetCore.Authentication.Certificate csomag legújabb stabil verzióját. Ez a csomag köztes szoftvereket biztosít a tanúsítványhitelesítéshez ASP.NET Core.

  10. Adjon hozzá egy új osztályt a SecureCertificateValidationService nevű project. Adja hozzá az alábbi kódot az osztályhoz a tanúsítványhitelesítés közbenső szoftverének konfigurálásához.

    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. Nyissa meg Program.cs , és cserélje le a kódot a Main metódusban a következő kódra:

    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();
     }
    

    A fenti kód úgy konfigurálja a Kestrel-kiszolgálót, hogy ügyféltanúsítványt igényeljen, és hozzáadja a tanúsítványhitelesítés közbenső szoftverét az alkalmazáshoz. A middleware a SecureCertificateValidationService osztály használatával ellenőrzi az ügyféltanúsítványt. A OnCertificateValidated rendszer meghívja az eseményt egy tanúsítvány érvényesítésekor. Ha a tanúsítvány érvényes, az esemény meghívja a metódust Success . Ha a tanúsítvány érvénytelen, az esemény hibaüzenettel hívja meg a Fail metódust, amelyet a rendszer visszaad az ügyfélnek.

  12. Kezdje el a project hibakeresését a webszolgáltatás elindításához. Az SSL-tanúsítvány megbízhatóságával és telepítésével kapcsolatos üzeneteket kaphat. Kattintson az Igen gombra minden egyes üzenet esetén a tanúsítvány elfogadásához és a projekt hibakeresésének folytatásához.

    Képernyőkép egy párbeszédpanelről, amely megkérdezi a felhasználót, hogy szeretne-e megbízni egy tanúsítványban

    Képernyőkép egy Windows-párbeszédpanelről, amely megkérdezi a felhasználót, hogy szeretne-e tanúsítványt telepíteni

  13. A webszolgáltatás a következő címen érhető el: https://localhost:7072/bank. A webszolgáltatást egy webböngésző megnyitásával és a webcím beírásával tesztelheti. A létrehozott időjárás-előrejelzési adatokat JSON formátumban fogja látni. Hagyja futni a webszolgáltatást az ügyfélalkalmazás létrehozása közben.

A ASP.NET Core vezérlőalapú webes API-k használatával kapcsolatos további információkért lásd: Webes API létrehozása ASP.NET Core.

Tanúsítványhitelesítést használó WinUI-alkalmazás létrehozása

Most, hogy már rendelkezik egy vagy több biztonságos webszolgáltatással, az alkalmazások tanúsítványokkal hitelesíthetik magukat ezekhez a webszolgáltatásokhoz. Ha a WinRT API-kból származó HttpClient-objektummal kér egy hitelesített webszolgáltatást, a kezdeti kérés nem tartalmaz ügyféltanúsítványt. A hitelesített webszolgáltatás ügyfél-hitelesítésre vonatkozó kéréssel válaszol. Ha ez történik, a Windows-ügyfél automatikusan lekérdezi a tanúsítványtárolót az elérhető ügyféltanúsítványok esetében. A felhasználó ezek közül a tanúsítványok közül választhat a webszolgáltatásban való hitelesítéshez. Egyes tanúsítványok jelszóval védettek, ezért meg kell adnia a felhasználónak a tanúsítvány jelszavának megadását.

Megjegyzés:

A tanúsítványok kezeléséhez még nincsenek Windows App SDK API-k. Az alkalmazás tanúsítványainak kezeléséhez a WinRT API-kat kell használnia. WinRT storage API-kat is használunk a tanúsítvány PFX-fájlból való importálásához. Számos WinRT API-t bármely Windows app használhat csomagidentitással, beleértve a WinUI-alkalmazásokat is.

Az általunk implementálandó HTTP kliens kód a .NET HttpClient-et használja. A WinRT API-kban található HttpClient nem támogatja az ügyféltanúsítványokat.

Ha nincsenek elérhető ügyféltanúsítványok, a felhasználónak hozzá kell adnia egy tanúsítványt a tanúsítványtárolóhoz. Olyan kódot is felvehet az alkalmazásba, amely lehetővé teszi a felhasználó számára egy ügyféltanúsítványt tartalmazó PFX-fájl kiválasztását, majd a tanúsítvány importálását az ügyféltanúsítvány-tárolóba.

Jótanács

A New-SelfSignedCertificate és az Export-PfxCertificate PowerShell-parancsmagokkal létrehozhat egy önaláírt tanúsítványt, és exportálhatja azt egy PFX-fájlba, amelyet ezzel a rövid útmutatóval használhat. Információért lásd: New-SelfSignedCertificate és Export-PfxCertificate.

Vegye figyelembe, hogy a tanúsítvány létrehozásakor mentse a tanúsítvány ujjlenyomatát a webszolgáltatásban az ellenőrzéshez.

  1. Nyissa meg Visual Studio, és hozzon létre egy új WinUI-project a kezdőlapon. Nevezze el az új project "FirstContosoBankApp" nevet. Kattintson a Create elemre az új project létrehozásához.

  2. A MainWindow.xaml fájlban adja hozzá a következő XAML-t egy Grid-elemhez , lecserélve a meglévő StackPanel-elemet és annak tartalmát. Ez az XAML tartalmazza az importálandó PFX-fájl keresésére szolgáló gombot, egy jelszóval védett PFX-fájl jelszavát megadó szövegmezőt, a kijelölt PFX-fájl importálására szolgáló gombot, a biztonságos webszolgáltatásba való bejelentkezéshez szükséges gombot, valamint egy szövegblokkot az aktuális művelet állapotának megjelenítéséhez.

    <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. Mentse a MainWindow módosításait .

  4. Nyissa meg a MainWindow.xaml.cs fájlt, és adja hozzá a következő using utasításokat.

    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. A MainWindow.xaml.cs fájlban adja hozzá a következő változókat a MainWindow osztályhoz. Megadják a "FirstContosoBank" webszolgáltatás biztonságos bejelentkezési szolgáltatásvégpontjának címét, valamint egy globális változót, amely a tanúsítványtárolóba importálandó PFX-tanúsítványt tartalmaz. Frissítse a <server-name> -t localhost:7072 -re vagy arra a portra, amelyik az API projekt launchSettings.json fájljának "https" konfigurációjában meg van adva.

    private Uri requestUri = new Uri("https://<server-name>/bank/login");
    private string pfxCert = null;
    
  6. A MainWindow.xaml.cs fájlban adja hozzá a következő kattintáskezelőt a bejelentkezési gombhoz, és hozzon létre egy metódust a biztonságos webszolgáltatás eléréséhez.

    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. Ezután adja hozzá a következő kattintáskezelőket: egyet a PFX-fájl tallózására szolgáló gombhoz, és egyet a kijelölt PFX-fájl tanúsítványtárolóba való importálására szolgáló gombhoz.

    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. Nyissa meg a Package.appxmanifest fájlt, és adja hozzá a következő képességeket a Képességek laphoz.

    • EnterpriseAuthentication
    • SharedUserCertificates
  9. Futtassa az alkalmazást, jelentkezzen be a biztonságos webszolgáltatásba, valamint importáljon egy PFX-fájlt a helyi tanúsítványtárolóba.

    Képernyőkép a WinUI-alkalmazásról a PFX-fájl tallózásához, tanúsítvány importálásához és biztonságos webszolgáltatásba való bejelentkezéshez szükséges gombokkal

Ezekkel a lépésekkel több olyan alkalmazást hozhat létre, amelyek ugyanazt a felhasználói tanúsítványt használják ugyanazon vagy különböző biztonságos webszolgáltatások access.

Windows Hello

Biztonság és identitás

Webes API létrehozása ASP.NET Core