Bagikan melalui


Berbagi sertifikat antar aplikasi Windows

Aplikasi Windows yang memerlukan autentikasi aman di luar kombinasi Id pengguna dan kata sandi dapat menggunakan sertifikat untuk autentikasi. Autentikasi sertifikat memberikan tingkat kepercayaan yang tinggi saat mengautentikasi pengguna. Dalam beberapa kasus, sekelompok layanan akan ingin mengautentikasi pengguna untuk beberapa aplikasi. Artikel ini memperlihatkan bagaimana Anda dapat mengautentikasi beberapa aplikasi Windows menggunakan sertifikat yang sama, dan bagaimana Anda dapat menyediakan metode bagi pengguna untuk mengimpor sertifikat yang disediakan untuk akses ke layanan web aman.

Aplikasi dapat mengautentikasi ke layanan web menggunakan sertifikat, dan beberapa aplikasi dapat menggunakan satu sertifikat dari penyimpanan sertifikat untuk mengautentikasi pengguna yang sama. Jika sertifikat tidak ada di penyimpanan, Anda dapat menambahkan kode ke aplikasi Anda untuk mengimpor sertifikat dari file PFX. Aplikasi klien dalam mulai cepat ini adalah aplikasi WinUI, dan layanan web adalah API web ASP.NET Core.

Tip

Microsoft Copilot adalah sumber daya yang bagus jika Anda memiliki pertanyaan tentang mulai menulis aplikasi Windows atau API web ASP.NET Core. Copilot dapat membantu Anda menulis kode, menemukan contoh, dan mempelajari selengkapnya tentang praktik terbaik untuk membuat aplikasi yang aman.

Prasyarat

  • Visual Studio dengan ASP.NET dan pengembangan web serta beban kerja pengembangan aplikasi Windows terinstal.
  • Windows Software Development Kit (SDK) terbaru untuk menggunakan WINDOWS Runtime (WinRT) API di aplikasi WinUI Anda.
  • PowerShell untuk bekerja dengan sertifikat yang ditandatangani sendiri.

Membuat dan menerbitkan layanan web aman

  1. Buka Microsoft Visual Studio dan pilih Buat proyek baru dari layar mulai.

  2. Dalam dialog Buat proyek baru, pilih API di daftar dropdown Pilih jenis proyek untuk memfilter templat proyek yang tersedia.

  3. Pilih templat ASP.NET Core Web API dan pilih Berikutnya.

  4. Beri nama aplikasi "FirstContosoBank" dan pilih Berikutnya.

  5. Pilih .NET 8.0 atau yang lebih baru sebagai Kerangka Kerja, atur Jenis autentikasi ke Tidak Ada, pastikan Konfigurasi untuk HTTPS dicentang, hapus centang Aktifkan dukungan OpenAPI, centang Jangan gunakan pernyataan tingkat atas dan Gunakan pengontrol, dan pilih Buat.

    Cuplikan layar Visual Studio membuat detail proyek baru untuk proyek API web ASP.NET Core

  6. Klik kanan file WeatherForecastController.cs di folder Pengontrol dan pilih Ganti Nama. Ubah nama menjadi BankController.cs dan biarkan Visual Studio mengganti nama kelas dan semua referensi ke kelas .

  7. Dalam file launchSettings.json, ubah nilai "launchUrl" dari "weatherforecast" menjadi "bank" untuk ketiga konfigurasi apa yang menggunakan nilai .

  8. Dalam file BankController.cs, tambahkan metode "Masuk" berikut.

    [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. Buka Manajer Paket NuGet dan cari dan instal versi stabil terbaru dari paket Microsoft.AspNetCore.Authentication.Certificate . Paket ini menyediakan middleware untuk autentikasi sertifikat di ASP.NET Core.

  10. Tambahkan kelas baru ke proyek bernama SecureCertificateValidationService. Tambahkan kode berikut ke kelas untuk mengonfigurasi middleware autentikasi sertifikat.

    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. Buka Program.cs dan ganti kode dalam metode Utama dengan kode berikut:

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

    Kode di atas mengonfigurasi server Kestrel untuk memerlukan sertifikat klien dan menambahkan middleware autentikasi sertifikat ke aplikasi. Middleware memvalidasi sertifikat klien menggunakan SecureCertificateValidationService kelas . Peristiwa OnCertificateValidated dipanggil ketika sertifikat divalidasi. Jika sertifikat valid, peristiwa akan memanggil Success metode . Jika sertifikat tidak valid, peristiwa memanggil Fail metode dengan pesan kesalahan, yang akan dikembalikan ke klien.

  12. Mulai debugging proyek untuk meluncurkan layanan web. Anda mungkin menerima pesan tentang mempercayai dan menginstal sertifikat SSL. Klik Ya untuk setiap pesan ini untuk mempercayai sertifikat dan melanjutkan penelusuran kesalahan proyek.

    Cuplikan layar dialog menanyakan kepada pengguna apakah mereka ingin mempercayai sertifikat

    Cuplikan layar dialog Windows yang menanyakan kepada pengguna apakah mereka ingin menginstal sertifikat

  13. Layanan web akan tersedia di https://localhost:7072/bank. Anda dapat menguji layanan web dengan membuka browser web dan memasukkan alamat web. Anda akan melihat data prakiraan cuaca yang dihasilkan yang diformat sebagai JSON. Jaga agar layanan web tetap berjalan saat Anda membuat aplikasi klien.

Untuk informasi selengkapnya tentang bekerja dengan API web berbasis pengontrol ASP.NET Core, lihat Membuat API web dengan ASP.NET Core.

Membuat aplikasi WinUI yang menggunakan autentikasi sertifikat

Sekarang setelah Anda memiliki satu atau beberapa layanan web yang aman, aplikasi Anda dapat menggunakan sertifikat untuk mengautentikasi ke layanan web tersebut. Saat Anda membuat permintaan ke layanan web terautentikasi menggunakan objek HttpClient dari API WinRT, permintaan awal tidak akan berisi sertifikat klien. Layanan web yang diautentikasi akan merespons dengan permintaan untuk autentikasi klien. Ketika ini terjadi, klien Windows akan secara otomatis meminta penyimpanan sertifikat untuk sertifikat klien yang tersedia. Pengguna Anda dapat memilih dari sertifikat ini untuk mengautentikasi ke layanan web. Beberapa sertifikat dilindungi kata sandi, jadi Anda harus memberi pengguna cara untuk memasukkan kata sandi untuk sertifikat.

Catatan

Belum ada API SDK Aplikasi Windows untuk mengelola sertifikat. Anda harus menggunakan API WinRT untuk mengelola sertifikat di aplikasi Anda. Kami juga akan menggunakan API penyimpanan WinRT untuk mengimpor sertifikat dari file PFX. Banyak API WinRT dapat digunakan oleh aplikasi Windows apa pun dengan identitas paket, termasuk aplikasi WinUI.

Kode klien HTTP yang akan kami terapkan menggunakan . HttpClient NET. HttpClient yang disertakan dalam API WinRT tidak mendukung sertifikat klien.

Jika tidak ada sertifikat klien yang tersedia, maka pengguna harus menambahkan sertifikat ke penyimpanan sertifikat. Anda dapat menyertakan kode di aplikasi yang memungkinkan pengguna memilih file PFX yang berisi sertifikat klien lalu mengimpor sertifikat tersebut ke penyimpanan sertifikat klien.

Tip

Anda dapat menggunakan cmdlet PowerShell New-SelfSignedCertificate dan Export-PfxCertificate untuk membuat sertifikat yang ditandatangani sendiri dan mengekspornya ke file PFX untuk digunakan dengan mulai cepat ini. Untuk informasi, lihat New-SelfSignedCertificate dan Export-PfxCertificate.

Perhatikan bahwa saat membuat sertifikat, Anda harus menyimpan thumbprint sertifikat untuk digunakan dalam layanan web untuk validasi.

  1. Buka Visual Studio dan buat proyek WinUI baru dari halaman mulai. Beri nama proyek baru "FirstContosoBankApp". Klik Buat untuk membuat proyek baru.

  2. Dalam file MainWindow.xaml, tambahkan XAML berikut ke elemen Grid, menggantikan elemen StackPanel yang ada dan kontennya. XAML ini menyertakan tombol untuk menelusuri file PFX yang akan diimpor, kotak teks untuk memasukkan kata sandi untuk file PFX yang dilindungi kata sandi, tombol untuk mengimpor file PFX yang dipilih, tombol untuk masuk ke layanan web aman, dan blok teks untuk menampilkan status tindakan saat ini.

    <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. Simpan perubahan MainWindow.

  4. Buka file MainWindow.xaml.cs, dan tambahkan pernyataan berikutusing.

    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. Dalam file MainWindow.xaml.cs, tambahkan variabel berikut ke kelas MainWindow . Mereka menentukan alamat untuk titik akhir layanan masuk aman dari layanan web "FirstContosoBank" Anda, dan variabel global yang menyimpan sertifikat PFX untuk diimpor ke penyimpanan sertifikat. <server-name> Perbarui ke localhost:7072 atau port mana pun yang ditentukan dalam konfigurasi "https" dalam file launchSettings.json proyek API Anda.

    private Uri requestUri = new Uri("https://<server-name>/bank/login");
    private string pfxCert = null;
    
  6. Dalam file MainWindow.xaml.cs, tambahkan penanganan klik berikut untuk tombol masuk dan metode untuk mengakses layanan web aman.

    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. Selanjutnya, tambahkan penanganan klik berikut untuk tombol untuk menelusuri file PFX dan tombol untuk mengimpor file PFX yang dipilih ke penyimpanan sertifikat.

    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. Buka file Package.appxmanifest dan tambahkan kemampuan berikut ke tab Kemampuan.

    • EnterpriseAuthentication
    • SharedUserCertificates
  9. Jalankan aplikasi Anda dan masuk ke layanan web aman Anda serta impor file PFX ke penyimpanan sertifikat lokal.

    Cuplikan layar aplikasi WinUI dengan tombol untuk menelusuri file PFX, mengimpor sertifikat, dan masuk ke layanan web aman

Anda dapat menggunakan langkah-langkah ini untuk membuat beberapa aplikasi yang menggunakan sertifikat pengguna yang sama untuk mengakses layanan web aman yang sama atau berbeda.

Windows Hello

Keamanan dan identitas

Membuat API web dengan ASP.NET Core