在 SharePoint 中自定义审核

原文链接

 

 

Ted Pattison

 

代码下载位置:OfficeSpace2008_09a.exe(631 KB)
在线浏览代码

 

 

SharePoint ® 技术的许多用户并未意识到 Windows ® SharePoint Services (WSS) 3.0 平台中直接内置了审核支持。这一特点没有广为人知,主要是由于 WSS 审核支持默认被关闭,WSS 也没有提供现成的选项启用该功能。要利用 WSS 审核基础架构,还需要 WSS 中没有的代码。
Microsoft ® Office SharePoint Server (MOSS) 2007 是利用 WSS 审核的一条捷径。MOSS 提供了用户界面(“站点设置”>“配置审核设置”下),让站点集合的所有者能启用并配置自动活动事件日志记录。MOSS 还提供了审核报告工具,用于读取审核日志条目并报告用户在特定站点集合内已执行的操作,如读写内容等。
WSS 审核支持的另一种使用方式对于开发人员很有吸引力。您可以使用 Visual Studio ® 构建自定义 SharePoint 解决方案,创建自定义应用程序页,允许站点集合管理员启用并配置 WSS 活动事件日志记录。但是,仅开启自动活动事件日志记录还是不够的。它还有其他要求。面向 WSS 的自定义审核解决方案还必须包含某种类型的用户界面,以便用户可以查看或报告已加入 WSS 审核日志的审核条目。
两年前,在 Microsoft 发布 MOSS 2007 的第一个公用测试版后的不久,Joanna Bichsel 和我发表了名为“使用 SharePoint Server 2007 实现项目级审核”的白皮书 ( msdn.microsoft.com/library/bb397403),以及辅助的代码示例。在该书中,我们就如何为 WSS 编写审核支持程序讨论了诸多重要的细节。我们还探讨了 MOSS 如何使用自定义策略和审核报告生成来充分利用并扩展 WSS 审核基础架构。
在本月的专栏中,我将演示我最近使用名为 AuditingDemo 的 Visual Studio 项目创建的新 SharePoint 解决方案。该项目包含一些我在白皮书中提及的审核管理代码,如通过 WSS 对象模型启用审核支持的代码。不过,AuditingDemo 项目已完全经过重新设计,与我两年前编写的代码相比,性能已大为提高。例如,使用 STSDEV 实用程序已创建了 AuditingDemo 项目,且我已在解决方案包部署、安全编程和安全修整等方面加入了许多最佳实践。
在本月的专栏中,我想说明这些更新的最佳实践和 SharePoint 开发技术。我的意图是对原来的白皮书做些补充,而不是推翻它的内容。如果您还未读过原来的白皮书,我建议您先看看这本书,以便了解本月专栏的历史渊源。

 

AuditingDemo 项目
AuditingDemo 项目旨在提供一个自定义 SharePoint 解决方案,它能利用 WSS 平台中内置的审核支持功能。设计这一项目时,我的想法是让站点集合的所有者(或担任审核管理员的其他用户)能启用、查看并修改当前站点集合的审核设置。AuditingDemo 项目还具备查看功能,这样,担任审核员的用户就能看到审核日志的内容,确定整个站点集合、每项或每个文档都出现了什么活动。
如前所述,此项目使用 STSDEV 实用程序构建,其下载位置是 codeplex.com/stsdev。我在 2008 年 3 月的 Office Space 专栏中 ( msdn.microsoft.com/magazine/cc337895) 也对此做了介绍。
AuditingDemo 项目是使用名为 AuditingDemo 的核心功能设计的,该功能在站点集合这一级别发挥作用。要使用 AuditingDemo,仅需在站点集合激活一次该功能即可。
AuditingDemo 功能包含带有 FeatureActivated 事件处理程序的功能接收器类(请参见 图 1)。在功能激活期间执行 FeatureActivated 中的代码,并完成两件重要的事情。第一,对整个网站集合完全启用审核日志记录。第二,它专门针对 AuditingDemo 解决方案创建数个安全对象。FeatureActivated 中的代码还特别新建两个 SharePoint 组和两个新的权限级别,以便站点集合管理员能新增担任审核员和审核管理员的用户。
 
图1. FeatureActivated 事件处理程序
 

 

public override void FeatureActivated(SPFeatureReceiverProperties 
  properties) {
  using (SPSite siteCollection = (SPSite)properties.Feature.Parent) {
    SPWeb TopLevelSite = siteCollection.RootWeb;

    // Turn on auditing flags.
    siteCollection.Audit.AuditFlags = SPAuditMaskType.All;
    siteCollection.Audit.Update();

    // create permission levels 
    SPRoleDefinition AuditorPermissions, AuditManagerPermissions;
    AuditorPermissions = CreatePermissionLevel(
      "Auditor Permissions", 
      "Can view audit logs",
      "Read");
    AuditManagerPermissions = CreatePermissionLevel(
      "Audit Manager Permissions", 
      "Can configure auditing support",
      "Design",
      SPBasePermissions.ManageWeb);

    // create Auditors group
    SPGroup Auditors = CreateGroup(
      "Auditors", 
      "for users who need to audit user activity");
    SPRoleAssignment AuditorRoleAssignment = new SPRoleAssignment(Auditors);
    AuditorRoleAssignment.RoleDefinitionBindings.Add(AuditorPermissions);
    TopLevelSite.RoleAssignments.Add(AuditorRoleAssignment);

    // create Audit Managers group
    SPGroup AuditManagers = CreateGroup(
      "Audit Managers", 
      "for users who configure WSS auditing support");
    SPRoleAssignment AuditManagerRoleAssignment = 
      new SPRoleAssignment(AuditManagers);
    AuditManagerRoleAssignment.RoleDefinitionBindings.Add(
      AuditManagerPermissions);
    TopLevelSite.RoleAssignments.Add(AuditManagersRoleAssignment);
}
 

 

 

注意,FeatureActivated 事件处理程序中的代码调用名为 CreatePermissionLevel 和 CreateGroup 的两个实用程序方法。我介绍这些是为了确保先删除任何与它们同名的旧安全对象。每个方法随后会创建请求的安全对象(权限级别或组),将其添加到顶层站点的相应集合内,并为调用程序返回强类型化的安全对象。CreatePermissionLevel 方法返回代表新权限级别的 SPRoleDefinition 对象,CreateGroup 方法返回 SPGroup。
注意,我是使用数个重载的实现设计的 CreatePermissionLevel 方法,它们的第三和第四个参数是可选参数。第三个参数用于传递现有权限级别的名称,该级别用于为新权限级别制作副本。例如,通过制作内置“读取”权限的副本来创建 AuditorPermissions 权限级别。通过制作内置“设计”权限的副本来创建 AuditManagerPermissions 权限级别。
CreatePermissionLevel 方法第四个参数的类型是 SPBasePermissions,用于额外传递一个或多个权限,随后可使用这些权限初始化新的权限级别。例如,对 CreatePermissionLevel(它创建 SPRoleDefinition 对象 AuditManagerPermissions)的调用会为第四个参数传递一个 ManageWeb 值。这意味着新权限级别是使用与内置“设计”权限相同的权限和 ManageWeb 权限创建的。
ManageWeb 权限十分重要,因为需要调整审核设置的用户要用到这一权限。我在本专栏的后面部分将介绍两项安全修整技术,它们用于向仅具有此权限的用户显示菜单项。
CreateGroup 方法的作用不只限于向顶层站点添加新组。它还可以向相关组的集合中添加新组,并将新组的 ID 加入名为 vti_associatemembergroup 的站点级属性中。当您想让新组显示在组的快速启动栏中和“添加用户”页面的组合框内,以便站点集合的所有者能更为直观地利用它向新组中添加用户时,这一代码非常重要。

创建支持审核配置的页面
AuditingDemo 项目提供三个自定义应用程序页面——AuditConfig.aspx、AuditLogViewer.aspx 和 ItemAudit.aspx——它们都是使用实践效果最好的技术开发的。例如,这些应用程序页面部署在 LAYOUTS 目录内名为 AuditingDemo 的特定解决方案目录下。为这些页面提供行为的代码已写入代码隐藏文件(例如 AuditConfig.cs)。该代码隐藏文件随后编译到项目的主程序集 AuditingDemo.dll 中,该程序集从全局程序集缓存 (GAC) 中安装并加载。
AuditConfig.aspx 应用程序页面为配置 WSS 审核支持提供了一个用户界面。我向 AuditingDemo 功能中添加了一个 CustomAction,以便具备 ManageWeb 权限的用户可以在站点设置页面上看到一个链接,使用该链接浏览 AuditConfig.aspx:
 
<!-- Add Link to Site Setting Page -->
<CustomAction
  Id="SiteActionsToolbar"
  GroupId="SiteCollectionAdmin"
  Location="Microsoft.SharePoint.SiteSettings"
  Sequence="0"
  Rights="ManageWebs"
  Title="Audit Management" >
  <UrlAction Url="~sitecollection/_layouts/AuditingDemo/AuditConfig.aspx"/>
</CustomAction>
 
注意,我是使用 SiteCollectionAdmin 的 GroupId 属性值和 Sequence 属性值 0 创建的这个自定义操作。这使该链接最先显示在“站点设置”页面的“站点集合管理”列中。
我随同 ManageWebs 值引入了 Rights 属性,WSS 用它提供声明性的安全修整。因此,只有具备 ManageWebs 权限的用户才能看到该链接。网站集合的所有者和其添加到审核管理员角色的任何用户皆属此列。
用户浏览 AuditConfig.aspx 时,会看到 图 2 中所示的 UI。如您所见,此应用程序页面提供了完全启用或禁用审核的单选按钮。您还能看到用于进入选择模式的单选按钮,在该模式下,用户可以精确选择在审核条目中记录的活动。
 
 
图 2 AuditConfig.aspx 允许用户配置审核日志记录
AuditConfig.aspx 的 OK 按钮的源代码相当简单。它读取用户选择了哪个单选按钮,并将当前站点集合的审核标志设置为合适的值。然后调用 Audit 属性的 Update 将更改记入内容数据库。
 
SPSite siteCollection = this.Site;
if (radAuditingOff.Checked) {
  siteCollection.Audit.AuditFlags = SPAuditMaskType.None;
}
if (radAuditingOnFull.Checked) {
  siteCollection.Audit.AuditFlags = SPAuditMaskType.All;
}
if (radAuditingOnSelective.Checked) {
  siteCollection.Audit.AuditFlags = GetSelectiveAuditingFlags();
}
siteCollection.Audit.Update();
 
如果用户已选择了可选审核配置选项,则会调用 GetSelectiveAuditingFlags 实用程序方法。它会检查所有这些复选框,并使用位或运算返回 SPAuditTypeMask 值,它代表用户为审核选择的所有类型活动的组合。
 
private SPAuditMaskType GetSelectiveAuditingFlags() {
  SPAuditMaskType AuditFlags = SPAuditMaskType.None;
  if (chkAuditView.Checked) {
    AuditFlags |= SPAuditMaskType.View;
  }
  if (chkAuditUpdate.Checked) {
    AuditFlags |= SPAuditMaskType.Update;
  }
  // Repeat for Copy, Move, Delete, Undelete, CheckIn, CheckOut,
  // Search, Workflow, SecurityChange, ProfileChange, SchemaChange
  return AuditFlags;
}
 
扩展站点操作菜单
我提供了浏览支持,以便用户可以到达 AuditLogViewer.aspx 应用程序页面。担任审核员的用户可利用该页查看站点发生的活动。考虑到许多担任审核员的用户不一定是管理员,可能绝不会因其他缘由访问“站点设置”页面,我没有在“站点设置”页面上放置另一链接。因此,使用自定义“站点操作”菜单项添加浏览支持似乎更为直观。我还能通过它为您展示如何利用程序化的安全修整创建弹出菜单。
如果您想要动态构建菜单项,您需要创建自定义的控件类并添加声明性的 CustomAction 元素,以实例化正确位置中的控件类实例。注意以下 CustomAction 元素与我先前所示的不同之处:
 
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Add Command to Site Actions Dropdown -->
  <CustomAction Id="AuditingSupport"
    GroupId="SiteActions"
    Location="Microsoft.SharePoint.StandardMenu"
    Sequence="1000"
    ControlClass="AuditingDemo.SiteActionsCustomSubMenu"
    ControlAssembly="AuditingDemo, [4-part name]"
    Title="Auditing Support"
    Description="Support for configuring and viewing auditing" />
</Elements>
 
两者的主要不同之处在于它使用 ControlClass 和 ControlAssembly 属性(而不是 UrlAction 元素)做出声明。这样就能使用自定义的控件类动态生成菜单项,例如 SiteActionsCustomSubMenu(AuditingDemo 项目中使用了这一控件类,如 图 3 的代码中所示)。注意,自定义控件类必须从 ASP.NET 编程模型提供的 WebControl 类进行继承。
 
图3 SiteActionsCustomSubMenu
 
public class SiteActionsCustomSubMenu : WebControl {

  protected override void OnLoad(EventArgs e) {
    this.EnsureChildControls();
    base.OnLoad(e);
  }

  protected override void CreateChildControls() {
    SPSite siteCollection = SPContext.Current.Site;
    SPWeb site = SPContext.Current.Web;
    SPUser user = site.CurrentUser;
    // provide security trimming
    if (IsCurrentUserInGroup("Auditors") ||
        IsCurrentUserInGroup("Audit Managers") ||
        user.IsSiteAdmin) {
      string siteCollectionPath = siteCollection.Url;
      if (!siteCollectionPath.EndsWith(@"/"))
        siteCollectionPath += "/";

      SubMenuTemplate smt = new SubMenuTemplate();
      smt.Text = "Auditing Support";
      smt.ID = "mnuAuditingSupport";
      smt.Description = "Configure and View Auditing";
      smt.ImageUrl = siteCollectionPath +
                     @"_layouts/images/AuditingDemo/AfricanPith32.gif";
      smt.Sequence = 400;

      MenuItemTemplate mit1 = new MenuItemTemplate();
      mit1.ID = "mnuAuditLog";
      mit1.Text = "Audit Log";
      mit1.Description = "Inspect Audit Entries";
      mit1.Sequence = 401;
      mit1.ClientOnClickNavigateUrl = siteCollectionPath +
        "_layouts/AuditingDemo/AuditLogViewer.aspx";
      mit1.ImageUrl = siteCollectionPath +
        @"_layouts/images/AuditingDemo/Binoculars32.gif";
      // add menu item to Controls collection
      smt.Controls.Add(mit1);
      // perform extra security trimming for menu for AuditConfig.aspx
      if (IsCurrentUserInGroup("Audit Managers") || user.IsSiteAdmin) {
        MenuItemTemplate mit2 = new MenuItemTemplate();
        mit2.ID = "mnuAuditingConfiguration";
        mit2.Text = "Auditing Configuration";
        mit2.Description = "Enable/Disable Auditing";
        mit2.Sequence = 402;
        mit2.ClientOnClickNavigateUrl = siteCollectionPath +
          "_layouts/AuditingDemo/AuditConfig.aspx";
        mit2.ImageUrl = siteCollectionPath +
          @"_layouts/images/AuditingDemo/Compass32.gif";
        smt.Controls.Add(mit2);
      }

      this.Controls.Add(smt);
    }
  }

  private bool IsCurrentUserInGroup(string GroupName) {
    SPWeb site = SPContext.Current.Web;
    foreach (SPGroup group in site.SiteGroups) {
      if (group.Name.Equals(GroupName)) {
        return group.ContainsCurrentUser;
      }
    }
    throw new ApplicationException("There is no group named " + 
      GroupName);
  }
}
 
CreateChildControls 方法提供了动态安全修整。注意,只有身为站点集合所有者或审核员/审核管理员组成员的用户才能看到完整的弹出菜单。第二个菜单项(允许用户浏览 AuditConfig.aspx 页面)做了更大的修整,排除了审核员组中的用户。只有身为站点集合的所有者或添加至审核管理员组的用户才能看到此菜单。
关于使用自定义控件类创建动态菜单,我还要提及另一个更重要的关键点。与 Web 部件类似,自定义控件类需要承载 Web 应用程序的 web.config 文件中的 SafeControl 条目。STSDEV 实用程序为添加此 SafeControl 提供了支持。它在 manifest.xml 文件中加入合适的元素,从而使所需的 SafeControl 条目能在场中部署 AuditingDemo.wsp 解决方案包时添加到一或多个 web.config 文件内。

查看审核日志条目
AuditingDemo 解决方案提供了 AuditLogViewer.aspx 自定义应用程序页,如 图 4 所示。该页面为用户提供了包含整个站点集合所有审核条目的视图。该页面上还有一个标题为“清除审核日志”的按钮。此按钮已经过安全修整处理,仅显示给站点集合的所有者。此按钮的源代码从审核日志删除了所有条目,在您测试自定义审核解决方案时这会很有帮助。
 


 
 
图 4 AuditLogViewer.aspx 显示审核日志条目
AuditLogViewer.aspx 的源代码使用 SPAuditQuery 对象在当前站点集合中查询审核日志。通过对 SPSite 对象的 Audit 属性调用 GetEntries 方法来运行查询。对 GetEntries 的调用会返回 SPAuditEntryCollection 对象,通过枚举该对象可检查每个视为 SPAuditEntry 对象的审核条目:
 
SPSite SiteCollection = SPContext.Current.Site;
  SPAuditQuery wssQuery = new SPAuditQuery(SiteCollection);
  SPAuditEntryCollection auditCol = 
    SiteCollection.Audit.GetEntries(wssQuery);
  foreach (SPAuditEntry entry in auditCol) {
    // enumererate through each audit entry
  }
 
通过 SPAuditEntryCollection 进行枚举以创建显示的方法有许多种。我使用的技术是动态创建 ADO.NET DataTable 对象,然后用每个审核条目的一行信息填充它。通过创建 DataTable,并将审核信息绑定到 SPGridView 控件来显示审核信息会变得相对简单些。
AuditLogViewer.aspx 页的源代码必须在安全方面进行特殊的处理。如果您检查那些查询审核日志的代码,就会看到它首先调用 RunWithElevatedPrivileges,以便其能以专用的 SHAREPOINT\System 帐户身份运行。由于查询审核日志属于特权操作,所以需要使用这项技术。
有时,也可能出现用户具备了审核员的身份,但却没有查询审核日志所需的必要权限的情形。因此,需要调用 RunWithElevatedPrivileges,这样即使当前用户没有所需的权限,代码也能查询审核日志。

逐项查看日志
AuditingDemo 项目中的第三个应用程序页是 ItemAudit.aspx。该页显示一个特殊项目或文档的审核条目。通过添加一个 CustomAction 元素可以浏览此页,该元素会向内置的 Item 内容类型新增一个 EditControlBlock (ECB) 菜单项:
 
<CustomAction Id="ItemAuditing.ECBItemMenu"
     RegistrationType="ContentType"
     RegistrationId="0x01"
     ImageUrl="/_layouts/images/GORTL.GIF"
     Location="EditControlBlock"
     Sequence="300"
     Title="View Audit History">
       <UrlAction Url=
   "~site/_layouts/AuditingDemo/ItemAudit.aspx?ItemId=
   {ItemId}&amp;ListId={ListId}"/>
   </CustomAction>
 
 
为 Item 内容类型配置的 CustomAction 还会应用到从 Item 继承的所有内容类型。由于所有内容类型均从 Item 类型继承而来,所以该技术可以有效地将 ECB 菜单项添加到整个站点集合的每个项目和文档中。
您可下载 AuditingDemo 示例代码,然后将其部署到场内的 SharePoint 开发机器上,以此检验这项技术。在某一特殊站点集合激活 AuditingDemo 功能后,您会看到每个项目和文档都有一个 ECB 菜单项,以“View Audit History”(查看审核历史记录)为标题。只要用户选择 ECB 菜单项,就会将其重定向至 ItemAudit.aspx 页,如 图 5 所示。


 
图 5 ItemAudit.aspx 显示特定项的审核条目
与 AuditLogViewer.aspx 页类似,ItemAudit.aspx 的源代码使用 SPAuditQuery 对象检索审核日志数据和 DataTable(用审核日志条目数据填充,然后绑定到 SPGridView 控件)。主要的区别是 ItemAudit.aspx 的源代码先调用 SPAuditQuery 对象的 RestrictToListItem 方法,然后再运行查询以过滤结果,这样找出的就是所关注的项目或文档。
请特别注意,SPAuditQuery 类还提供了其他两种筛选方法:RestrictToList 和 RestrictToUser,以便您可以查看特殊列表或特殊用户的审核条目。另请注意,您还可使用 RestrictToUser 与 RestrictToListItem 或 RestrictToList 方法的组合确定列表或列表项具体涉及哪位用户。

请将您想向 Ted 询问的问题和提出的意见发送至 mmoffice@microsoft.com

Ted Pattison 是一名作家、培训师兼 SharePoint 领域的 MVP,现居住在美国佛罗里达州的坦帕市。他刚刚完成了《Inside Windows SharePoint Services 3.0》 一书,该书由 Microsoft Press 出版。他还自己开办了公司 Ted Pattison Group (www.TedPattison.net),为专业开发人员提供 SharePoint 高级培训。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值