Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Basicamente, proteger dados consiste nos seguintes passos:
- Crie um protetor de dados de um fornecedor de proteção de dados.
- Chama o
Protectmétodo com os dados que queres proteger. - Chama o
Unprotectmétodo com os dados que queres transformar de volta em texto simples.
A maioria dos frameworks e modelos de aplicações, como ASP.NET Core ou SignalR, já configuram o sistema de proteção de dados e adicionam-no a um contentor de serviços que é acedido através de injeção de dependências. O exemplo seguinte demonstra:
- Configurar um contentor de serviço para injeção de dependências e registar a camada de proteção de dados.
- Recebendo o fornecedor de proteção de dados via DI.
- Criar um protetor.
- Proteger e depois desproteger os dados.
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!
*/
Quando crias um protetor, deves fornecer uma ou mais Cordas de Propósito. Uma cadeia de propósitos proporciona isolamento entre os consumidores. Por exemplo, um protetor criado com uma cadeia de propósito "verde" não seria capaz de desproteger dados fornecidos por um protetor com o propósito de "roxo".
Sugestão
Instâncias de IDataProtectionProvider e IDataProtector são "thread-safe" para múltiplas chamadas. Pretende-se que, uma vez que um componente recebe uma referência a an IDataProtector através de uma chamada para CreateProtector, ele use essa referência para múltiplas chamadas para Protect e Unprotect.
Uma chamada para Unprotect lançará CryptographicException se a carga protegida não puder ser verificada ou decifrada. Alguns componentes podem querer ignorar erros durante operações sem proteção; um componente que lê cookies de autenticação pode tratar este erro e considerar o pedido como se não tivesse cookie de todo, em vez de rejeitar o pedido imediatamente. Os componentes que desejam este comportamento devem identificar especificamente o CryptographicException em vez de engolir todas as exceções.
Utilize a função AddOptions para configurar um repositório personalizado
Considere o seguinte código que utiliza um fornecedor de serviços porque a implementação de IXmlRepository depende de um serviço singleton:
public void ConfigureServices(IServiceCollection services)
{
// ...
var sp = services.BuildServiceProvider();
services.AddDataProtection()
.AddKeyManagementOptions(o => o.XmlRepository = sp.GetService<IXmlRepository>());
}
O código anterior regista o seguinte aviso:
Chamar 'BuildServiceProvider' a partir do código da aplicação resulta na criação de uma cópia adicional dos serviços singleton. Considere alternativas como serviços de injeção de dependência como parâmetros para 'Configurar'.
O seguinte código fornece a IXmlRepository implementação sem necessidade de construir o fornecedor de serviços e, portanto, fazer cópias adicionais dos serviços singleton:
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();
}
O código anterior remove a chamada para GetService e oculta IConfigureOptions<T>.
O código seguinte mostra o repositório XML personalizado:
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();
}
}
}
O seguinte código mostra a classe XmlKey:
public class XmlKey
{
public Guid Id { get; set; }
public string Xml { get; set; }
public XmlKey()
{
this.Id = Guid.NewGuid();
}
}