Entity Framework Connector
O pacote opcional Lacuna PKI Entity Framework Connector possibilita as seguintes integrações entre o SDK e o Microsoft Entity Framework:
- Compressão e descompressão de assinaturas CAdES armazenando as LCRs e certificados em banco de dados
- Criação e validação de assinaturas CAdES com referência de revogação porém sem valores de revogação armazenando os valores em banco de dados
- Enviar mensagens de log geradas pelo SDK para o banco de dados
- Armazenamento de nonces criptográficos no banco de dados para autenticação com certificados digitais
Note
O pacote assume que o Entity Framework está sendo usado sob o modelo Code First
Utilizando armazenamento em banco de dados
A classe EntityFrameworkStore, incluída no pacote opcional, implementa a interface ISimpleStore, utilizada pelo SDK quando um storage externo é necessário (para mais informações, veja Pacotes nuget opcionais).
Para utilizá-la, você deve fazer a classe DbContext
do seu projeto implementar a interface
IPkiStoreContext, o que basicamente significa adicionar um DbSet
com objetos do
tipo PkiStoreObject à sua classe:
public class MyDbContext : DbContext, IPkiStoreContext {
// ...
DbSet<PkiStoreObject> PkiStore { get; set; }
// ...
}
Se o seu projeto estiver usando automatic migrations, essa alteração ao DbContext
irá fazer com que uma nova tabela
com nome "LacunaPkiStore" seja criada no banco de dados. Se o seu projeto estiver usando code-based migrations, as
alterações necessárias ao banco de dados aparecerão na próxima migração criada.
O próximo passo é instanciar a classe EntityFrameworkStore passando uma instância
do seu DbContext
, tipicamente dentro de um bloco using
:
using (var dbContext = new MyDbContext()) {
// ...
var store = new EntityFrameworkStore(dbContext);
// ...
});
Tendo uma instância da classe EntityFrameworkStore
, você pode utilizá-la em qualquer lugar que o SDK exija um
ISimpleStore
, por exemplo para comprimir e descomprimir assinaturas CAdES:
byte[] precomputedSignature = ...; // qualquer assinatura CAdES, não necessariamente feita com o SDK
var compressedSignature = CadesSignatureCompression.Compress(precomputedSignature, store);
var decompressedSignature = CadesSignatureCompression.Decompress(compressedSignature, store);
Warning
A classe EntityFrameworkStore
não chama o método SaveChanges()
, você mesmo precisa chamá-lo.
A motivação para o comportamento de não chamar o método SaveChanges()
automaticamente é permitir que o programador
faça por exemplo uma compressão de assinatura CAdES como parte de uma transação. Portanto, assegure-se de que o método
SaveChanges()
será chamado ao final do processo:
using (var dbContext = new MyDbContext()) {
// ...
byte[] precomputedSignature = ...; // qualquer assinatura CAdES, não necessariamente feita com o SDK
var store = new EntityFrameworkStore(dbContext);
var compressedSignature = CadesSignatureCompression.Compress(precomputedSignature, store);
// ...
dbContext.SaveChanges();
});
Enviando logs para o banco de dados
A classe EntityFrameworkLogger é utilizada para enviar logs gerados pelo SDK para
o banco de dados. Para utilizá-la, você deve fazer a classe DbContext
do seu projeto imeplementar a interface
IPkiLogContext, o que basicamente significa adicionar um DbSet
com objetos do
tipo PkiLogEntry à sua classe:
public class MyDbContext : DbContext, IPkiLogContext {
// ...
DbSet<PkiLogEntry> PkiLog { get; set; }
// ...
}
Se o seu projeto estiver usando automatic migrations, essa alteração ao DbContext
irá fazer com que uma nova tabela
com nome "LacunaPkiLog" seja criada no banco de dados. Se o seu projeto estiver usando code-based migrations, as
alterações necessárias ao banco de dados aparecerão na próxima migração criada.
A partir de então, basta incluir no código de inicialização do seu site ou aplicação uma chamada ao método estático
Configure(IPkiLogContext, LogLevels)
da classe EntityFrameworkLogger
passando uma instância do seu DbContext
:
EntityFrameworkLogger.Configure(new MyDbContext());
Tip
A classe EntityFrameworkLogger
chama automaticamente o método SaveChanges()
do DbContext
à medida que achar
necessário. Portanto, você deve passar na chamada ao método Configure()
uma instância exclusiva do seu DbContext
.
Utilizando armazenamento de nonces criptográficos em banco de dados
A classe EntityFrameworkNonceStore, incluída no pacote opcional, implementa a interface INonceStore, utilizada pelo SDK para armazenar nonces criptográficos durante a autenticação com certificados digitais.
Para utilizá-la, você deve fazer a classe DbContext
do seu projeto implementar a interface
IPkiNonceStoreContext, o que basicamente significa adicionar um DbSet
com objetos
do tipo PkiNonce à sua classe:
public class MyDbContext : DbContext, IPkiNonceStoreContext {
// ...
DbSet<PkiNonce> PkiNonces { get; set; }
// ...
}
Se o seu projeto estiver usando automatic migrations, essa alteração ao DbContext
irá fazer com que uma nova tabela
com nome "LacunaPkiNonces" seja criada no banco de dados. Se o seu projeto estiver usando code-based migrations, as
alterações necessárias ao banco de dados aparecerão na próxima migração criada.
O próximo passo é instanciar a classe EntityFrameworkNonceStore
passando uma instância do seu DbContext
, tipicamente
dentro de um bloco using
:
using (var dbContext = new MyDbContext()) {
// ...
var nonceStore = new EntityFrameworkNonceStore(dbContext);
// ...
});
Tendo uma instância da classe EntityFrameworkNonceStore
, você pode utilizá-la para realizar autenticações com
certificados digitais.
public class AuthenticationController : ApiController {
public IHttpActionResult Get() {
byte[] nonce;
using (var dbContext = new DbContext()) {
var nonceStore = new EntityFrameworkNonceStore(dbContext);
var certAuth = new PKCertificateAuthentication(nonceStore);
nonce = certAuth.Start();
}
var response = new AuthenticationGetResponse() {
Nonce = nonce
};
return Ok(response);
}
public IHttpActionResult Post(AuthenticationPostRequest request) {
ValidationResults vr;
PKCertificate certificate;
using (var dbContext = new DbContext()) {
var nonceStore = new EntityFrameworkNonceStore(dbContext);
var certAuth = new PKCertificateAuthentication(nonceStore);
vr = certAuth.Complete(request.Nonce, request.Certificate, request.Signature, TrustArbitrators.Windows, out certificate);
}
// Check authentication result
if (!vr.IsValid) {
// This failure is perfectly normal, it happens everytime a user tries to sign in
// with an expired or revoked certificate, for instance.
return Ok(new AuthenticationPostResponse() {
Success = false,
Message = "Authentication failed",
ValidationResults = vr.ToString()
});
}
// ----------------------------------------------------------------------------------------
// At this point, you have assurance that the certificate is valid according to the
// TrustArbitrator you selected above and that the user is indeed the certificate's
// subject. Now, you'd typically query your database for a user that matches one of the
// certificate's fields, such as cert.EmailAddress or cert.PkiBrazil.CPF and set the user
// ID on the auth cookie. For demonstration purposes, we'll set the email address directly
// on the cookie as if it were the user ID.
// ----------------------------------------------------------------------------------------
FormsAuthentication.SetAuthCookie(certificate.EmailAddress, false);
// Inform the page of the success
return Ok(new AuthenticationPostResponse() {
Success = true
});
}
}
Tip
A classe EntityFrameworkNonceStore
por padrão chama o método SaveChanges()
por conta própria, não é necessário
chamá-lo manualmente.
Para mais informações veja o tópico Autenticação com certificado.
Dependência do pacote Entity Framework
Para maximizar a compatibilidade, o pacote depende de uma versão antiga do pacote EntityFramework. Entretanto, recomendamos fortemente que seja utilizada a versão mais atual do pacote.
Código-fonte
O código-fonte do pacote é aberto, ficando hospedado no BitBucket. Caso queira customizá-lo, você pode fazer um fork do projeto e utilizar a sua versão customizada ao invés do pacote opcional.