Question Comment chiffrer les données dans Entity Framework Code First?


J'ai essayé et échoué à trouver une bonne approche pour chiffrer les données SQL avec Entity Framework Code First. Je dois commencer par ceci avec ce que j'héberge dans Azure et je n'ai pas accès au cryptage SQL natif.

Prendre une page de La sécuritéJ'ai entièrement mis en œuvre une approche qui utilise SaveChanges et ObjectMaterialized pour gérer le chiffrement / déchiffrement des entités, mais lors des tests, j'ai constaté que cette méthode était trop peu fiable pour être utilisée.

Voici un exemple de mise en œuvre:

public override int SaveChanges()
{
    var pendingEntities = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager
        .GetObjectStateEntries(EntityState.Added | EntityState.Modified)
        .Where(en => !en.IsRelationship).ToList();

    foreach (var entry in pendingEntities) //Encrypt all pending changes
        EncryptEntity(entry.Entity);

    int result = base.SaveChanges();

    foreach (var entry in pendingEntities) //Decrypt updated entities for continued use
        DecryptEntity(entry.Entity);

    return result;
}

void ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
{
    DecryptEntity(e.Entity);
}

J'ai vu d'autres articles qui chiffrent / déchiffrent manuellement via des propriétés secondaires, comme ceci:

public Value { get; set; }

[NotMapped]
public DecryptedValue
{
    get { return Decrypt(this.Value); }
    set { this.Value = Encrypt(value); }
}

Cela fonctionnera très certainement, mais je trouve que cette approche est moins qu'idéale. Lorsque vous utilisez cette approche, tous les développeurs doivent parcourir toutes les propriétés chiffrées pour trouver celles qu’ils peuvent utiliser.

La solution la plus idéale serait que je puisse remplacer l’obtention / le réglage de chaque valeur au niveau de l’accès aux données. Y a-t-il un moyen de faire cela? Dans la négative, comment puis-je implémenter le cryptage des données avec Entity Framework - Code First pour qu'il soit facile à gérer et à utiliser?


13
2018-04-08 17:28


origine


Réponses:


J'ai de bonnes nouvelles. L’instabilité que je rencontrais avec l’approche SaveChanges / ObjectMaterialized était due au fait que DetectChanges() n'est pas appelée jusqu'à ce que DbContext effectue réellement la sauvegarde.

J'ai pu résoudre ce problème en appelant DetectChanges() avant que je tire les enregistrements ajoutés / modifiés de la ObjectStateManager. Cela a permis d'éliminer les bizarreries d'état d'objet qui provoquaient un comportement de chiffrement incohérent.

Le code résultant étant:

public override int SaveChanges()
{
    var contextAdapter = ((IObjectContextAdapter)this);

    contextAdapter.ObjectContext.DetectChanges();

    var pendingEntities = contextAdapter.ObjectContext.ObjectStateManager
        .GetObjectStateEntries(EntityState.Added | EntityState.Modified)
        .Where(en => !en.IsRelationship).ToList();

    foreach (var entry in pendingEntities) //Encrypt all pending changes
        EncryptEntity(entry.Entity);

    int result = base.SaveChanges();

    foreach (var entry in pendingEntities) //Decrypt updated entities for continued use
        DecryptEntity(entry.Entity);

    return result;
}

MODIFIER - Ajout d’un exemple de DataContext pour voir ma solution de bout en bout pour le chiffrement de toutes les entités. Remarque: Vous n'avez pas besoin d'utiliser un attribut personnalisé pour chiffrer les propriétés. La source


11
2018-04-10 06:01