Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Приложения Windows, требующие безопасной проверки подлинности за пределами сочетания идентификаторов пользователя и пароля, могут использовать сертификаты для проверки подлинности. Проверка подлинности сертификата обеспечивает высокий уровень доверия при проверке подлинности пользователя. В некоторых случаях группа служб требует проверки подлинности пользователя для нескольких приложений. В этой статье показано, как выполнить проверку подлинности нескольких приложений Windows с помощью одного сертификата и как можно предоставить способ импорта сертификата, предоставленного для access защищенных веб-служб.
Приложения могут проходить проверку подлинности в веб-службе с помощью сертификата, а несколько приложений могут использовать один сертификат из хранилища сертификатов для проверки подлинности одного пользователя. Если сертификат не существует в магазине, вы можете добавить код в приложение для импорта сертификата из PFX-файла. Клиентское приложение в этом кратком руководстве — это приложение WinUI 3, а веб-служба — это веб-API ASP.NET Core.
Совет
Microsoft Copilot — отличный ресурс, если у вас есть вопросы о том, как начать писать приложения для Windows или веб-API на ASP.NET Core. Copilot поможет вам написать код, найти примеры и узнать больше о рекомендациях по созданию безопасных приложений.
Предварительные требования
- Visual Studio с установленными рабочими нагрузками ASP.NET и веб-разработки и разработки приложений WinUI.
- Последний Пакет средств разработки программного обеспечения (SDK) для использования API Windows Runtime (WinRT) в приложении WinUI.
- PowerShell для работы с самозаверяющими сертификатами.
Создание и публикация защищенной веб-службы
Откройте Microsoft Visual Studio и выберите Создать новый проект на стартовом экране.
В диалоговом окне "Создание нового проекта" выберите API в выпадающем списке Выберите тип проекта, чтобы отфильтровать доступные шаблоны проектов.
Выберите шаблон ASP.NET Core веб-API и выберите Next.
Присвойте приложению имя FirstContosoBank и нажмите кнопку "Далее".
Выберите .NET 8.0 или более поздней версии в качестве Framework, задайте тип Authentication значение None, убедитесь, что установлен флажок Настроить для HTTPS, снимите флажок Enable OpenAPI support, поставьте отметку "Не используйте операторы верхнего уровня" и "Использовать контроллеры", и выберите Create.
Щелкните правой кнопкой мыши файл WeatherForecastController.cs в папке "Контроллеры" и выберите "Переименовать". Измените имя на BankController.cs и позвольте Visual Studio переименовать класс и все ссылки на класс.
В файле launchSettings.json измените значение launchUrl с "weatherforecast" на "bank" для всех трех конфигураций, которые используют значение.
В файле BankController.cs добавьте следующий метод 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"; }Откройте Package Manager NuGet и найдите последнюю стабильную версию пакета Microsoft.AspNetCore.Authentication.Certificate. Этот пакет предоставляет ПО промежуточного слоя для проверки подлинности сертификатов в ASP.NET Core.
Добавьте новый класс в project с именем SecureCertificateValidationService. Добавьте следующий код в класс, чтобы настроить ПО промежуточного слоя проверки подлинности сертификата.
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; } } }Откройте Program.cs и замените код в методе Main следующим кодом:
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(); }Приведенный выше код настраивает сервер Kestrel для требования сертификата клиента и добавляет ПО промежуточного слоя проверки подлинности сертификата в приложение. ПО промежуточного слоя проверяет сертификат клиента с помощью
SecureCertificateValidationServiceкласса. СобытиеOnCertificateValidatedвызывается при проверке сертификата. Если сертификат действителен, событие вызываетSuccessметод. Если сертификат недопустим, событие вызываетFailметод с сообщением об ошибке, которое будет возвращено клиенту.Начните отладку проекта, чтобы запустить веб-службу. Вы можете получать сообщения о доверии и установке SSL-сертификата. Щелкните Yes для каждого из этих сообщений, чтобы доверять сертификату и продолжить отладку project.
Веб-служба будет доступна по адресу
https://localhost:7072/bank. Вы можете протестировать веб-службу, открыв веб-браузер и введя веб-адрес. Вы увидите созданные данные прогноза погоды в формате JSON. Сохраняйте работу веб-службы при создании клиентского приложения.
Дополнительные сведения о работе с контроллерными веб-API в ASP.NET Core см. в разделе Создание веб-API с ASP.NET Core.
Создание приложения WinUI, использующего проверку подлинности сертификата
Теперь, когда у вас есть одна или несколько защищенных веб-служб, приложения могут использовать сертификаты для проверки подлинности в этих веб-службах. При выполнении запроса к проверенной веб-службе с помощью объекта HttpClient из API WinRT первоначальный запрос не будет содержать сертификат клиента. Аутентифицированная веб-служба отвечает на запрос аутентификации клиента. При этом клиент Windows автоматически запрашивает сертификаты в хранилище для доступных клиентских сертификатов. Пользователь может выбрать из этих сертификатов для аутентификации в веб-службе. Некоторые сертификаты защищены паролем, поэтому пользователю нужно предоставить способ ввода пароля для сертификата.
Примечание.
Пока нет Windows App SDK API для управления сертификатами. Для управления сертификатами в приложении необходимо использовать API WinRT. Мы также будем использовать API WinRT storage для импорта сертификата из PFX-файла. Многие API WinRT могут использоваться любым приложением Windows с идентичностью пакета, включая приложения WinUI.
Код HTTP-клиента, который мы реализуем, использует HttpClient из .NET. HttpClient, включенный в API WinRT, не поддерживает сертификаты клиентов.
Если нет доступных сертификатов клиента, пользователю потребуется добавить сертификат в хранилище сертификатов. В приложение можно включить код, позволяющий пользователю выбрать PFX-файл, содержащий сертификат клиента, а затем импортировать этот сертификат в хранилище сертификатов клиента.
Совет
Командлеты PowerShell New-SelfSignedCertificate и Export-PfxCertificate можно использовать для создания самоподписанного сертификата и его экспорта в файл формата PFX для использования с этим кратким руководством. Дополнительные сведения см. в разделе New-SelfSignedCertificate и Export-PfxCertificate.
Обратите внимание, что при создании сертификата необходимо сохранить отпечаток сертификата, который будет использоваться в веб-службе для проверки.
Откройте Visual Studio и создайте новый проект WinUI на начальной странице. Назовите новый проект "FirstContosoBankApp". Щелкните Create, чтобы создать новый project.
В файле MainWindow.xaml добавьте следующий код XAML в элемент Grid, заменив существующий элемент StackPanel и его содержимое. Этот XAML-файл содержит кнопку для выбора PFX-файла для импорта, текстовое поле для ввода пароля для PFX-файла, защищенного паролем, кнопку для импорта выбранного PFX-файла, кнопку для входа в защищенный веб-сервис и текстовый блок для отображения состояния текущего действия.
<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"/>Сохраните изменения в MainWindow.
Откройте файл MainWindow.xaml.cs и добавьте следующие
usingинструкции.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;В файле MainWindow.xaml.cs добавьте следующие переменные в класс MainWindow . Они указывают адрес для конечной точки защищенной службы входа в веб-службу FirstContosoBank и глобальную переменную, содержащую сертификат PFX для импорта в хранилище сертификатов. Обновите
<server-name>наlocalhost:7072или порт, указанный в настройках "https" в файле launchSettings.json проекта API.private Uri requestUri = new Uri("https://<server-name>/bank/login"); private string pfxCert = null;В файле MainWindow.xaml.cs добавьте следующий обработчик нажатия кнопки входа и метод для обращения к защищенной веб-службе.
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(); }Затем добавьте следующие обработчики нажатия кнопки, чтобы найти PFX-файл и кнопку импорта выбранного PFX-файла в хранилище сертификатов.
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(); }Откройте файл Package.appxmanifest и добавьте следующие возможности на вкладку "Возможности".
- Корпоративная аутентификация
- ОбщиеПользовательские сертификаты
Запустите приложение и войдите в безопасную веб-службу, а также импортируйте PFX-файл в локальное хранилище сертификатов.
Эти действия можно использовать для создания нескольких приложений, использующих один и тот же сертификат пользователя для access одинаковых или разных защищенных веб-служб.
Связанный контент
Windows developer