ASP.NET Core'da Veri Koruma API'lerini kullanmaya başlama

Temel olarak, verilerin korunması aşağıdaki adımlardan oluşur:

  1. Bir veri koruma sağlayıcısından veri koruyucusu oluşturun.
  2. Protect Korumak istediğiniz verilerle yöntemini çağırın.
  3. Düz metne Unprotect geri döndürmek istediğiniz verilerle yöntemini çağırın.

ASP.NET Core veya SignalRgibi çoğu çerçeve ve uygulama modeli, veri koruma sistemini zaten yapılandırır ve bağımlılık ekleme yoluyla erişilen bir hizmet kapsayıcısına ekler. Aşağıdaki örnekte gösterilmiştir:

  • Bağımlılık ekleme ve veri koruma yığınını kaydetme için bir hizmet kapsayıcısı yapılandırma.
  • DI aracılığıyla veri koruma sağlayıcısını alma.
  • Koruyucu oluşturma.
  • Koruma ve ardından verilerin korumasını kaldırma.
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!
 */

Bir koruyucu oluşturduğunuzda bir veya daha fazla Amaç Dizesi sağlamanız gerekir. Amaç dizesi tüketiciler arasında yalıtım sağlar. Örneğin, "yeşil" amaç dizesiyle oluşturulan bir koruyucu, bir koruyucu tarafından "mor" amacıyla sağlanan verilerin korumasını kaldıramaz.

Bahşiş

ve IDataProtector örnekleriIDataProtectionProvider, birden çok arayan için iş parçacığı açısından güvenlidir. Bir bileşen çağrısı aracılığıyla bir başvuru IDataProtector aldığında ve Unprotectöğesine yapılan birden çok çağrı CreateProtectoriçin bu başvuruyı Protect kullanması amaçlanmıştır.

Unprotect Korumalı yük doğrulanamıyorsa veya deşifre edilemiyorsa çağrısı CryptographicException oluşturur. Bazı bileşenler korumasını kaldırma işlemleri sırasında hataları yoksaymak isteyebilir; kimlik doğrulamasını cookieokuyan bir bileşen bu hatayı işleyebilir ve isteğin başarısız olması yerine hiç yokmuş cookie gibi davranabilir. Bu davranışı isteyen bileşenler, tüm özel durumları yutmak yerine özellikle CryptographicException'ı yakalamalıdır.

Özel depo yapılandırmak için AddOptions kullanma

uygulamasının IXmlRepository tek bir hizmete bağımlılığı olduğundan hizmet sağlayıcısı kullanan aşağıdaki kodu göz önünde bulundurun:

public void ConfigureServices(IServiceCollection services)
{
    // ...

    var sp = services.BuildServiceProvider();
    services.AddDataProtection()
      .AddKeyManagementOptions(o => o.XmlRepository = sp.GetService<IXmlRepository>());
}

Yukarıdaki kod aşağıdaki uyarıyı günlüğe kaydeder:

Uygulama kodundan 'BuildServiceProvider' çağrısı, tekil hizmetlerin ek bir kopyasının oluşturulmasına neden olur. Bağımlılık ekleme hizmetlerini 'Yapılandır' parametresi olarak ekleme gibi alternatifleri göz önünde bulundurun.

Aşağıdaki kod, hizmet sağlayıcısını IXmlRepository oluşturmak ve bu nedenle tekil hizmetlerin ek kopyalarını oluşturmak zorunda kalmadan uygulamayı sağlar:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<DataProtectionDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    // Register XmlRepository for data protection.
    services.AddOptions<KeyManagementOptions>()
    .Configure<IServiceScopeFactory>((options, factory) =>
    {
        options.XmlRepository = new CustomXmlRepository(factory);
    });

    services.AddRazorPages();
}

Yukarıdaki kod çağrısı GetService kaldırır ve gizler IConfigureOptions<T>.

Aşağıdaki kod özel XML deposunu gösterir:

using CustomXMLrepo.Data;
using Microsoft.AspNetCore.DataProtection.Repositories;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

public class CustomXmlRepository : IXmlRepository
{
    private readonly IServiceScopeFactory factory;

    public CustomXmlRepository(IServiceScopeFactory factory)
    {
        this.factory = factory;
    }

    public IReadOnlyCollection<XElement> GetAllElements()
    {
        using (var scope = factory.CreateScope())
        {
            var context = scope.ServiceProvider.GetRequiredService<DataProtectionDbContext>();
            var keys = context.XmlKeys.ToList()
                .Select(x => XElement.Parse(x.Xml))
                .ToList();
            return keys;
        }
    }

    public void StoreElement(XElement element, string friendlyName)
    {
        var key = new XmlKey
        {
            Xml = element.ToString(SaveOptions.DisableFormatting)
        };

        using (var scope = factory.CreateScope())
        {
            var context = scope.ServiceProvider.GetRequiredService<DataProtectionDbContext>();
            context.XmlKeys.Add(key);
            context.SaveChanges();
        }
    }
}

Aşağıdaki kod XmlKey sınıfını gösterir:

public class XmlKey
{
    public Guid Id { get; set; }
    public string Xml { get; set; }

    public XmlKey()
    {
        this.Id = Guid.NewGuid();
    }
}