模拟身份与权限提升
问题背景:某网站下存在两个列表库,用户Test1对List1具有参与讨论权限,用户Test2对List2具有参与讨论权限;而这两个用户对其他列表均只有读取权限;
问题内容:要求Test1每对List1添加一项,则List2 也增加一项相关的记录;
问题关键:SPItemEventRevicer,SPSecurity.RunWithElevatedPrivileges
解决:
自定义类,继承类SPItemEventRevicer,实现 ItemAdded方法,在对List1添加完一项之后,将该项的ID保存,同时在List2中新建一项,将ID值赋予。
在对List2进行写入操作时,由于当前HttpContext的用户是test1,所以会出现异常。所以要用到SPSecurity.RunWithElevatedPrivileges,临时以system身份运行。需要注意的是:此时要取到List2,是不能直接用当前的SPWeb或者其他对象的,因为这些对象的权限仍旧是Test1的权限,需要新建实例。
另外,在以system身份运行中,如果觉得权限过大,可以进行其他身份模拟;即:在新建一个SPSite对象的时候,把某个用户SPUser的UserToken用户信息赋值给SPSite对象,则该SPSite对象的所有操作都以该模拟用户身份进行。
代码:
{
private string strSiteUrl = string.Empty;
private string strWebName = string.Empty;
private string strParentWebUrl = "/au/";//网站之下的网站
public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
using (SPWeb web = properties.OpenWeb())
{
strSiteUrl = web.Site.Url;
strWebName = web.Name;
SPList List1 = web.Lists[properties.ListId];
SPListItem list1Item = properties.ListItem;
Guid m_Guid = Guid.NewGuid();
list1Item["Index"] = m_Guid;//为新建项创建一个Guid,并赋值给其Index字段
list1Item.Update();//一定要Update
InsertIntoAnswerList(m_Guid);
}
}
private void InsertIntoAnswerList(Guid m_Guid)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
try
{
using (SPSite site = new SPSite(strSiteUrl))//注意在这里一定要新建一个SPSite对象,在获取其他对象如:SPWeb
{
using (SPWeb web = site.OpenWeb(strParentWebUrl + strWebName))
{
SPList List2 = web.Lists["AnswerList"];
SPListItem list2Item = answerList.Items.Add();
list2Item["Index"] = m_Guid.ToString();//将Guid值赋给List2中的某个字段
list2Item.Update();
}
}
}
catch(Exception ex)
{
//获取异常信息,由于dll文件是要放在GAC里的,获取错误信息的方法只好通过日志察看器了。
EventLog urlLog = new EventLog();
urlLog.Source = "Application";
StringBuilder strbException = new StringBuilder();
strbException.Append("Message:");
strbException.Append(ex.Message);
strbException.Append("\r\n");
strbException.Append("Source:");
strbException.Append(ex.Source);
strbException.Append("\r\n");
strbException.Append("Strack:");
strbException.Append(ex.StackTrace);
strbException.Append("\r\n");
urlLog.WriteEntry(strbException.ToString(), EventLogEntryType.Error);
}
});
}
}
在SPSecurity.RunWithElevatedPrivileges()中的代码以system身份运行,也可模拟其他用户身份。
SPUser user = site.RootWeb.SiteUsers["sharepointweb\\user1"];
//利用用户Token构造新的Site对象
SPSite siteWithUser = new SPSite(siteUrl, user.UserToken);
此后SPSite则会以User1的身份进行运行。