在應用程式之間共用憑證

需要使用者識別碼和密碼組合之外的安全身分憑證的通用 Windows 平台 (UWP) 應用程式可以使用憑證進行驗證。 驗證使用者時,憑證驗證可提供高度的信任。 在某些情況下,服務群組需要驗證多個應用程式的使用者。 本文說明如何使用相同的憑證來驗證多個應用程式,以及如何為使用者提供方便的程式碼來匯入提供的憑證,以存取受保護的 Web 服務。

應用程式可以使用憑證向 Web 服務進行驗證,而多個應用程式可以使用憑證儲存的單一憑證來驗證相同的使用者。 如果商店中不存在憑證,您可以將程式代碼新增至您的應用程式,以從 PFX 檔案匯入憑證。

啟用 Microsoft Internet Information Services (IIS) 和用戶端憑證對應

本文使用 Microsoft Internet Information Services (IIS) 作為範例。 預設情況下不啟用 IIS。 您可以使用控制台啟用 IIS。

  1. 打開「控制台」,然後選擇程式”。
  2. 選取 [開啟或關閉 Windows 功能] 選項。
  3. 展開 Internet Information Services,然後展開全球資訊網服務。 展開應用程式開發功能,然後選擇 ASP.NET 3.5ASP.NET 4.5。 選取這些選項會自動啟用 Internet Information Services
  4. 按一下確定以套用變更。

建立並發佈安全的 Web 服務

  1. 以管理員身分執行 Microsoft Visual Studio,然後從開始頁面中選擇新專案。 需要管理員存取權限才能將 Web 服務發佈到 IIS 伺服器。 在「新專案」對話方塊中,將架構變更為 .NET Framework 3.5。 選擇 Visual C# ->Web ->Visual Studio ->ASP.NET Web 服務應用程式。 將應用程式命名為「FirstContosoBank」。 按一下 [確定] 以建立專案。

  2. Service1.asmx.cs 檔案中,將預設的 HelloWorld Web 方法替換為下列「Login」方法。

            [WebMethod]
            public string Login()
            {
                // Verify certificate with CA
                var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(
                    this.Context.Request.ClientCertificate.Certificate);
                bool test = cert.Verify();
                return test.ToString();
            }
    
  3. 儲存 Service1.asmx.cs 檔案。

  4. 方案總管 中,以滑鼠右鍵按一下「FirstContosoBank」應用程式,然後選取發佈

  5. 發佈 Web 對話方塊中,建立新的設定檔,並將其命名為「ContosoProfile」。 按一下 [下一步] 。

  6. 在下一頁上,輸入 IIS 伺服器的伺服器名稱,並指定網站名稱「Default Web Site/FirstContosoBank」。 按一下發佈,以發佈您的 Web 服務。

設定您的 Web 服務以使用用戶端憑證驗證

  1. 執行 Internet Information Services (IIS) 管理員
  2. 展開 IIS 伺服器的網站。 在預設網站下,選擇新的「FirstContosoBank」Web 服務。 在動作區段中,選取進階設定...
  3. 應用程式集區設定為 .NET v2.0,然後按一下確定
  4. Internet Information Services (IIS) 管理員中,選擇您的 IIS 伺服器,然後按兩下伺服器憑證。 在動作區段中,選擇建立自我簽署憑證...。輸入「ContosoBank」作為憑證的易記名稱,然後按一下確定。 這將以「<伺服器名稱>.<網域名稱>」的形式建立一個供 IIS 伺服器使用的新憑證。
  5. Internet Information Services (IIS) 管理員中,選取預設網站。 在動作區段中,選擇繫結,然後按一下新增...。類型選擇「https」,將連接埠設定為「443」,然後輸入 IIS 伺服器的完整主機名稱 (<伺服器名稱>.<網域名稱>」)。 將 SSL 憑證設定為「ContosoBank」。 按一下 [確定]。 按一下網站繫結視窗中的關閉
  6. Internet Information Services (IIS) 管理員中,選擇「FirstContosoBank」Web 服務。 按兩下 SSL 設定。 按一下需要 SSL。 在用戶端憑證下,選擇需要。 在動作區段中,按一下套用
  7. 您可以透過開啟 Web 瀏覽器並輸入下列 Web 位址,來驗證 Web 服務是否設定正確:「https://<伺服器名稱>.<網域名稱>/FirstContosoBank/Service1.asmx」。 例如:「https://myserver.example.com/FirstContosoBank/Service1.asmx"。 如果您的 Web 服務已正確設定,系統會提示您選擇用戶端憑證以存取 Web 服務。

您可以重複上述步驟,來建立可使用相同用戶端憑證存取的多個 Web 服務。

建立使用憑證驗證的 UWP 應用程式

現在您已經擁有一個或多個安全的 Web 服務,您的應用程式可以使用憑證對這些 Web 服務進行驗證。 當您使用 HttpClient 物件向經過驗證的 Web 服務發出要求時,初始要求將不包含用戶端憑證。 經過驗證的 Web 服務將回應用戶端驗證要求。 發生這種情況時,Windows 用戶端將自動查詢憑證儲存以取得可用的用戶端憑證。 您的使用者可以從這些憑證中進行選擇,以對 Web 服務進行驗證。 有些憑證受密碼保護,因此您需要為使用者提供輸入憑證密碼的方法。

如果沒有可用的用戶端憑證,則使用者需要將憑證新增至憑證儲存。 您可以在應用程式中包含程式碼,使使用者能夠選擇包含用戶端憑證的 PFX 檔案,然後將該憑證匯入到用戶端憑證存放區中。

提示 您可以使用 makecert.exe 建立一個 PFX 檔案,以搭配本快速入門使用。 如需使用 makecert.exe 的詳細資訊,請參閱 MakeCert。

 

  1. 開啟 Visual Studio 並從開始頁面建立新專案。 將新專案命名為「FirstContosoBankApp」。 按一下 [確定] 建立新專案。

  2. 在 MainPage.xaml 檔案中,將以下 XAML 新增至預設 Grid 元素。 此XAML 包括一個用於瀏覽要匯入的PFX 檔案的按鈕、一個用於為受密碼保護的PFX 檔案輸入密碼的文字方塊、一個用於匯入所選PFX 檔案的按鈕、一個用於登入安全 Web 服務的按鈕,以及顯示目前動作狀態的文字區塊。

    <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. 儲存 MainPage.xaml 檔案。

  4. 在 MainPage.xaml.cs 檔案中,加入以下 using 陳述式。

    using Windows.Web.Http;
    using System.Text;
    using Windows.Security.Cryptography.Certificates;
    using Windows.Storage.Pickers;
    using Windows.Storage;
    using Windows.Storage.Streams;
    
  5. 開啟 MainPage.xaml.cs 檔案,並將下列變數新增至 MainPage 類別。 它們指定「FirstContosoBank」Web 服務安全性「登入」方法的位址,以及儲存要匯入到憑證存放區中 PFX 憑證的全域變數。 將<伺服器名稱>更新為 Microsoft Internet Information Server (IIS) 伺服器的完整伺服器名稱。

    private Uri requestUri = new Uri("https://<server-name>/FirstContosoBank/Service1.asmx?op=Login");
    private string pfxCert = null;
    
  6. 在 MainPage.xaml.cs 檔案中,為登入按鈕和存取安全 Web 服務的方法新增以下點擊處理常式。

    private void Login_Click(object sender, RoutedEventArgs e)
    {
        MakeHttpsCall();
    }
    
    private async void MakeHttpsCall()
    {
    
        StringBuilder result = new StringBuilder("Login ");
        HttpResponseMessage response;
        try
        {
            Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient();
            response = await httpClient.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. 在 MainPage.xaml.cs 檔案中,為瀏覽 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 succeded";
        }
        catch (Exception ex)
        {
            Result.Text = "Certificate import failed with " + ex.Message;
        }
    }
    
    private async void Browse_Click(object sender, RoutedEventArgs e)
    {
    
        StringBuilder result = new StringBuilder("Pfx file selection ");
        FileOpenPicker pfxFilePicker = new FileOpenPicker();
        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. 執行您的應用程式並登入您的安全 Web 服務,並將 PFX 檔案匯入本機憑證存放區。

您可以使用這些步驟建立多個應用程式,這些應用程式會使用相同的使用者憑證來存取相同或不同的安全 Web 服務。