【问题标题】:Audit trail: Web application审计跟踪:Web 应用程序
【发布时间】:2011-05-06 12:10:49
【问题描述】:

我正在从事一个审计跟踪项目,我们被告知要跟进。

使用影子表跟踪我们数据库中的所有表(200+),就像 Hibernate Envers 一样。因此,我们为涉及 CUD 的每个事务创建了快照。

过去,我为每个客户实施了针对有限的重要数据集的审计解决方案。对于目前的工作,我的问题是:

  1. 审计数据库中的每个表是否有意义?
  2. 像 Envers 那样跟踪数据有多大价值?任何应用程序都希望有特定数据点的增量。查询大量数据以找出增量似乎是不现实的。
  3. 类似 Envers 的解决方案需要将 CUD 操作与有效排除触发器的事务绑定在一起。这是因为触发器在它们自己的事务中运行,因此影子表中的数据可能会在应用程序的事务回滚的情况下不同步。我在这里缺少什么吗?
  4. 是否有人建议使用 NoSQL DB 进行审计跟踪?

【问题讨论】:

    标签: database audit trail


    【解决方案1】:

    完全实现,可以进一步改进。我希望这可以帮助某人:

    public partial  class Entity:DbContext
        {
    
          public enum AuditActions {I,U,D}
    
          public override int SaveChanges( )
          {
              ChangeTracker.DetectChanges(); 
              ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext;
              // string UserName = WindowsIdentity.GetCurrent().Name;
              IPrincipal principal = Thread.CurrentPrincipal;
              IIdentity identity = principal == null ? null : principal.Identity;
              string name = identity == null ? "" : identity.Name;
    
              //Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity((userName), roles);
              List<ObjectStateEntry> objectStateEntryList =
                  ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added
                                                             | EntityState.Modified
                                                             | EntityState.Deleted)
                  .ToList();
    
              List<DBAudit> AuditList = new List<DBAudit>();
    
              string Audittable = string.Empty; 
              foreach (ObjectStateEntry entry in objectStateEntryList)
              {
                   Audittable = entry.EntitySet.ToString();
    
                   if (!entry.IsRelationship && Audittable!="Audit table name")
                  {
    
                      //sIsAuditTble =entry.EntitySet="DBAudit"? true:false;
                      switch (entry.State)
                      {
                          case EntityState.Added:
                            AuditList=  LogDetails(entry, name, AuditActions.I);
                              break;
                          case EntityState.Deleted:
                            AuditList=  LogDetails(entry, name, AuditActions.D);
                              break;
                          case EntityState.Modified:
                            AuditList=  LogDetails(entry, name, AuditActions.U);
                               break;
    
                      }
                  }
              }
    
    
    
                  using (var context = new ProjectTrackerEntities())
                  {
                      for (int i = 0; i < AuditList.Count; i++)
                      {
                          context.DBAudits.Add(AuditList[i]);
                          context.SaveChanges();
                      }
                  }
    
              return base.SaveChanges();
          }
    
          public List<DBAudit> LogDetails(ObjectStateEntry entry, string UserName, AuditActions action)
          {
              List<DBAudit> dbAuditList = new List<DBAudit>();
    
            if (action == AuditActions.I)
              {
    
                  var keyValues = new Dictionary<string, object>();
                  var currentValues = entry.CurrentValues;
    
                 // entry.Entity key = new EntityKey();
    
                      DBAudit audit = new DBAudit();
                      audit.AuditId = Guid.NewGuid().ToString();
                      audit.RevisionStamp = DateTime.Now;
                      audit.TableName = entry.EntitySet.Name;
                      audit.UserName = UserName;
                      audit.OldData = "";
                      audit.Actions = action.ToString();
                      for (int i = 0; i < currentValues.FieldCount; i++)
                      {
                      audit.ChangedColumns = audit.ChangedColumns + currentValues.GetName(i);
                      audit.NewData = audit.NewData + currentValues.GetValue(i);
                      audit.ChangedColumns = audit.ChangedColumns + ", ";
                      audit.NewData = audit.NewData + ", ";
                      }
                      dbAuditList.Add(audit);
                      //LogSave(audit);
    
    
    
    
              }
              else if (action == AuditActions.D)
              {
                  var keyValues = new Dictionary<string, object>();
                  var DeletedValues = entry.OriginalValues;
    
                  // entry.Entity key = new EntityKey();
    
    
                  DBAudit audit = new DBAudit();
                  audit.AuditId = Guid.NewGuid().ToString();
                  audit.RevisionStamp = DateTime.Now;
                  audit.TableName = entry.EntitySet.Name;
                  audit.UserName = UserName;
                  audit.NewData = "";
    
                  audit.Actions = action.ToString();
                  for (int i = 0; i < DeletedValues.FieldCount; i++)
                  {
                      audit.ChangedColumns = audit.ChangedColumns + DeletedValues.GetName(i);
                      audit.OldData = audit.OldData + DeletedValues.GetValue(i);
                      audit.ChangedColumns = audit.ChangedColumns + ", ";
                      audit.OldData = audit.OldData + ", ";
                  }
                  dbAuditList.Add(audit);
              }
              else 
              {
    
                      foreach (string propertyName in entry.GetModifiedProperties())
                      {
                          DBAudit audit = new DBAudit();
                          DbDataRecord original = entry.OriginalValues;
                          string oldValue = original.GetValue(original.GetOrdinal(propertyName)).ToString();
    
                          CurrentValueRecord current = entry.CurrentValues;
                          string newValue = current.GetValue(current.GetOrdinal(propertyName)).ToString();
    
                          audit.AuditId = Guid.NewGuid().ToString();
                          audit.RevisionStamp = DateTime.Now;
                          audit.TableName = entry.EntitySet.Name;
                          audit.UserName = UserName;
                          audit.ChangedColumns = propertyName;
                          audit.OldData = oldValue;
                          audit.NewData = newValue;
                          audit.Actions = action.ToString();
                          dbAuditList.Add(audit);
                          //LogSave(audit);
    
    
                        }
    
              }
    
            return dbAuditList;
    
    
          }
    
    
    
        }
    

    【讨论】:

    • 欢迎您,在这里,解释为什么要使用您的解决方案而不只是如何使用是一个很好的做法。这将使您的答案更有价值,并帮助进一步的读者更好地理解您是如何做到的。我还建议您查看我们的常见问题解答:stackoverflow.com/faq
    【解决方案2】:

    NoSQL 数据库的一个选项是RavenDB,使用它的“versioning bundle”。

    虽然现在可能还为时过早,但我最近听了一个有趣的 Herding code 插曲,他们在其中 talk with Eric Sink on about Veracity。据我了解,Veracity 部分是分布式版本控制系统,部分是 NoSQL 数据库。它被设计成任何东西的后端,从源代码控制系统到 wiki。它已经开发了几年,但实际上仍处于测试前阶段(截至 2010 年 11 月)。

    【讨论】:

    猜你喜欢
    • 2013-04-10
    • 2018-06-25
    • 2011-03-15
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多