ASP.NET Core 的取用者 API 概觀

IDataProtectionProviderIDataProtector 介面是取用者使用資料保護系統的基本介面。 它們位於 Microsoft.AspNetCore.DataProtection.Abstractions 套件中。

IDataProtectionProvider

提供者介面代表資料保護系統的根目錄。 無法直接用來保護或取消保護資料。 取用者必須藉由呼叫 IDataProtectionProvider.CreateProtector(purpose) 來取得對 IDataProtector 的參考,其目的是描述預定取用者使用案例的字串。 如需此參數的意圖,以及如何選擇適當值的詳細資訊,請參閱目的字串

IDataProtector

保護裝置介面是由呼叫 CreateProtector 傳回,而此介面是取用者可用來執行保護和解除保護作業的介面。

若要保護資料片段,請將資料傳遞至 Protect 方法。 基本介面會定義方法,這個方法會轉換 byte[] - > byte[],但也有一個多載 (提供為擴充方法),可轉換字串 - > 字串。 兩種方法所提供的安全性相同;開發人員應該選擇最適合其使用案例的多載。 無論選擇的多載為何,Protect 方法傳回的值現在都會受到保護 (加密和防竄改),而且應用程式可以將它傳送至不受信任的用戶端。

若要取消保護先前保護的資料片段,請將受保護的資料傳遞至 Unprotect 方法。 (有 byte[] 型和字串型多載,可方便開發人員使用。)如果先前呼叫此相同 IDataProtector 上對 Protect 呼叫所產生的受保護承載,則 Unprotect 方法會傳回未受保護的原始承載。 如果受保護的承載遭到竄改或由不同的 IDataProtector 產生,則 Unprotect 方法會擲回 CryptographicException。

相同與不同 IDataProtector 的概念與目的概念有聯繫。 如果兩個 IDataProtector 實例是從相同的根 IDataProtectionProvider 產生,但透過呼叫 IDataProtectionProvider.CreateProtector 中的不同用途字串,則視為不同的保護裝置,其中一個實例將無法解除保護另一個實例所產生的承載。

使用這些介面

對於 DI 感知元件,預期的用法是元件在其建構函式中採用 IDataProtectionProvider 參數,且當元件具現化時,DI 系統會自動提供此服務。

注意

某些應用程式 (例如主控台應用程式或 ASP.NET 4.x 應用程式) 可能不是 DI 感知,因此無法使用這裡所述的機制。 如需在不透過 DI 的情況下取得 IDataProtection 提供者實例的詳細資訊,請參閱非 DI 感知案例文件中的這些案例。

下列範例示範三個概念:

  1. 將資料保護系統新增新增至服務容器,

  2. 使用 DI 接收 IDataProtectionProvider 的實例,以及

  3. IDataProtectionProvider 建立 IDataProtector,並使用它來保護和解除保護資料。

主控台應用程式

using System;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;

public class Program
{
    public static void Main(string[] args)
    {
        // add data protection services
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddDataProtection();
        var services = serviceCollection.BuildServiceProvider();

        // create an instance of MyClass using the service provider
        var instance = ActivatorUtilities.CreateInstance<MyClass>(services);
        instance.RunSample();
    }

    public class MyClass
    {
        IDataProtector _protector;

        // the 'provider' parameter is provided by DI
        public MyClass(IDataProtectionProvider provider)
        {
            _protector = provider.CreateProtector("Contoso.MyClass.v1");
        }

        public void RunSample()
        {
            Console.Write("Enter input: ");
            string input = Console.ReadLine();

            // protect the payload
            string protectedPayload = _protector.Protect(input);
            Console.WriteLine($"Protect returned: {protectedPayload}");

            // unprotect the payload
            string unprotectedPayload = _protector.Unprotect(protectedPayload);
            Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
        }
    }
}

/*
 * SAMPLE OUTPUT
 *
 * Enter input: Hello world!
 * Protect returned: CfDJ8ICcgQwZZhlAlTZT...OdfH66i1PnGmpCR5e441xQ
 * Unprotect returned: Hello world!
 */

Web 應用程式

Program.cs 中呼叫 AddDataProtection(IServiceCollection, Action<DataProtectionOptions>)

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddDataProtection();

var app = builder.Build();

下列醒目提示的程式碼示範如何在控制器中使用 IDataProtector

public class HomeController : Controller
{
    private readonly IDataProtector _dataProtector;

    public HomeController(IDataProtectionProvider dataProtectionProvider)
    {
        _dataProtector = dataProtectionProvider.CreateProtector("HomeControllerPurpose");
    }

    // ...

    public IActionResult Privacy()
    {
        // The original data to protect
        string originalData = "original data";

        // Protect the data (encrypt)
        string protectedData = _dataProtector.Protect(originalData);
        Console.WriteLine($"Protected Data: {protectedData}");

        // Unprotect the data (decrypt)
        string unprotectedData = _dataProtector.Unprotect(protectedData);
        Console.WriteLine($"Unprotected Data: {unprotectedData}");

        return View();
    }
    
    // ...

套件 Microsoft.AspNetCore.DataProtection.Abstractions 包含擴充方法 GetDataProtector,可方便開發人員使用。 它會封裝為單一作業,並從服務提供者擷取 IDataProtectionProvider 和呼叫 IDataProtectionProvider.CreateProtector。 下列範例示範其用法:

using System;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
 
public class Program
{
    public static void Main(string[] args)
    {
        // add data protection services
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddDataProtection();
        var services = serviceCollection.BuildServiceProvider();
 
        // get an IDataProtector from the IServiceProvider
        var protector = services.GetDataProtector("Contoso.Example.v2");
        Console.Write("Enter input: ");
        string input = Console.ReadLine();
 
        // protect the payload
        string protectedPayload = protector.Protect(input);
        Console.WriteLine($"Protect returned: {protectedPayload}");
 
        // unprotect the payload
        string unprotectedPayload = protector.Unprotect(protectedPayload);
        Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
    }
}

提示

IDataProtectionProviderIDataProtector 的執行個體對多個呼叫而言是安全執行緒。 一旦元件透過呼叫 CreateProtector 取得對 IDataProtector 的參考,就會將該參考使用於對 ProtectUnprotect 的多次呼叫。 如果無法驗證或解碼受保護的承載,則對 Unprotect 的呼叫將會擲回 CryptographicException。 某些元件可能會想要在解除保護作業期間忽略錯誤;讀取驗證 cookie 的元件可能會處理此錯誤,並將要求視為完全沒有 cookie,而不是完全失敗要求。 想要此行為的元件應該特別攔截 CryptographicException,而不是吞沒所有例外狀況。