设为首页 收藏本站
查看: 1226|回复: 0

[经验分享] SharePoint 列表权限控制

[复制链接]

尚未签到

发表于 2015-9-24 08:15:43 | 显示全部楼层 |阅读模式
  一提到sharepoint 我相信权限控制一定会是一个很重要的话题,尤其是对列表的权限控制,创建、修改、查看权限。其实网上这方面的资料已经很多了,尤其是以下2篇文章,后来索性把CodeArt_PermissionEx的源代码下载下来,然后仔细阅读了以下。
  利用开源SharePoint Permission Extension插件对SharePoint 的列表进行权限控制!
  通过代码解决SharePoint列表视图权限分配问题
  要想完全明白源码设计的原理 建议大家先阅读再议WSS RenderingTemplate 对sharepoint模板覆盖有一个简单的了解。我把CodeArt_PermissionEx仔细阅读了一下并且修改了里面的一些代码(个人觉得原作者C#基本功一般,sharepoint方面还是不错,我这里修改的是VS2013版的源码)。修改后部署到sharepoint2013上如图:
DSC0000.png
  内容内型权限设计如图:
DSC0001.png
  这里的PersonType是一个自定义内容内型,每一个内型这里有一个人员和组的权限控制,主要控制user是否可以新建记录,比如user不在PersonType内容内型人员和组里面,那么这个user将不能创建记录,没有权限的user进入后看到的结果如图:
DSC0002.png
  看到这里的新建项目变为不可用了。
  这里说说查找权限的方式,首先我们需要的我们的设置保存起来,
  1)根据我们的类容类型来找权限设置,如果没有任何权限设置那么我们就直接返回true;
  2)如果当前用户是管理员用户直接返回true;
  3)在指定的人员里面查找当前user是否存在,存在返回true;
  4)指定的组里面是否包含当前user,存在返回true;否则返回false
相关代码如下:


DSC0003.gif DSC0004.gif


public bool CheckRight(SPUser user, string contentTypeName)
{
ContentTypeCreateSetting set = this.GetContentTypeCreateSetting(contentTypeName);
if (set == null)
return true;
return set.CanCreate(user);
}
public bool CanCreate(SPUser currentUser)
{
if (currentUser != null && currentUser.IsSiteAdmin) return true;
if (String.IsNullOrEmpty(this.SpecialAccounts) && String.IsNullOrEmpty(this.SpecialGroups))
return true;
if (currentUser == null)
{
return false;
}
bool inAccounts = this.IsInSpecialAccounts(currentUser.LoginName);
if (inAccounts)
return true;
return this.IsInSpecialGroups(currentUser);
}
}
View Code  主要原理是新建列表数据默认用到的是NewMenu类,这里我们开发一个带有权限控制的子类NewMenuWithPermission,主要代码如下:





   public class NewMenuWithPermission : NewMenu
{        
private ListContentTypesCreateSetting _setting;
bool _settingExist = true ;
bool UserHaveRight(string cName)
{
if (!_settingExist)
return true;
if (_setting == null)
{
_setting = ListContentTypesCreateSetting.GeSetting(base.List);
_settingExist = _setting != null;
}
if (_setting == null)
return true ;
return _setting.CheckRight(SPContext.Current.Web.CurrentUser, cName);
//return true;
        }

public override MenuItemTemplate AddMenuItem(string id, string displayName, string imageUrl, string description, string navigateUrl, string onClickScript)
{         
MenuItemTemplate m = base.AddMenuItem(id, displayName, imageUrl, description, navigateUrl, onClickScript);
m.Visible = this.UserHaveRight(displayName);
return m;
}

}
View Code  如何让sharepoint使用我们这个NewMenuWithPermission类,这里我们需要覆盖sharepoint的DocumentLibraryViewToolBar 和 ViewToolBar模板,相关代码如下:





<SharePoint:RenderingTemplate ID="DocumentLibraryViewToolBar" runat="server">
<Template>
<wssuc:ToolBar CssClass="ms-menutoolbar" EnableViewState="false" id="toolBarTbl" ButtonSeparator="<img src='/_layouts/15/images/blank.gif' alt=''>" RightButtonSeparator="  " runat="server">
<Template_Buttons>
<codeart:NewMenuWithPermission  runat="server" AccessKey="<%$Resources:wss,tb_NewMenu_AK%>"/>
<%--<SharePoint:NewMenu ID="NewMenu1" Visible="false" AccessKey="<%$Resources:wss,tb_NewMenu_AK%>" runat="server"/>--%>
<SharePoint:UploadMenu ID="UploadMenu1" AccessKey="<%$Resources:wss,tb_UploadMenu_AK%>" runat="server"/>
<SharePoint:ActionsMenu ID="ActionsMenu1" AccessKey="<%$Resources:wss,tb_ActionsMenu_AK%>" runat="server"/>
<SharePoint:SettingsMenu ID="SettingsMenu1" AccessKey="<%$Resources:wss,tb_SettingsMenu_AK%>" runat="server"/>
</Template_Buttons>
<Template_RightButtons>
<SharePoint:PagingButton ID="PagingButton1" runat="server"/>
<SharePoint:ListViewSelector ID="ListViewSelector1" runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
</Template>
</SharePoint:RenderingTemplate>
<SharePoint:RenderingTemplate ID="ViewToolBar" runat="server">
<Template>
<wssuc:ToolBar CssClass="ms-menutoolbar" EnableViewState="false" id="toolBarTbl" ButtonSeparator="<img src='/_layouts/15/images/blank.gif' alt=''>" RightButtonSeparator="  " runat="server">
<Template_Buttons>
<codeart:NewMenuWithPermission  runat="server" AccessKey="<%$Resources:wss,tb_NewMenu_AK%>"/>
<%--<SharePoint:NewMenu AccessKey="<%$Resources:wss,tb_NewMenu_AK%>" runat="server" />--%>
<SharePoint:ActionsMenu AccessKey="<%$Resources:wss,tb_ActionsMenu_AK%>" runat="server" />
<SharePoint:SettingsMenu AccessKey="<%$Resources:wss,tb_SettingsMenu_AK%>" runat="server" />
</Template_Buttons>
<Template_RightButtons>
<SharePoint:PagingButton runat="server"/>
<SharePoint:ListViewSelector runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
</Template>
</SharePoint:RenderingTemplate>
View Code  现在我们来查看view的权限设计
DSC0005.png
  没有权限的人访问时运行结果如下:
DSC0006.png
  
  这里的view权限查找方式和控制方式与上面内容内型权限控制都是一样的,下面提到的字段权限设计也是一样的原理。只是这里我们需要开发一个PermissionListViewSelector类来扩展默认的ViewSelectorMenu类,实现代码如下:





public class PermissionListViewSelector : ViewSelectorMenu // Microsoft.SharePoint.WebControls.ListViewSelector
    {
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
//if (!this.Context.User.Identity.IsAuthenticated)//for anonymous access
//{
//    return;
//}
var currentUser = base.Web.CurrentUser;
if (currentUser != null && currentUser.IsSiteAdmin)
{
return;
}
SPList curList = SPContext.Current.List;
ListViewPermissionSetting listSetting = ListViewPermissionSetting.GetListSetting(curList);
if (listSetting == null)
{
return;
}
if (SPContext.Current.ViewContext == null || SPContext.Current.ViewContext.View == null)
return;
SPView currentView = SPContext.Current.ViewContext.View;
ViewPermission viewSetting = listSetting.GetByViewID(currentView.ID);
if (viewSetting == null)
return;
if (( viewSetting!= null) && (!(viewSetting.CanDisplay(currentUser))))
{
//如果用户没有权限访问当前视图,那么需要计算其有权限访问的试图
if (currentView.DefaultView) //如果访问默认视图而没有权限时,自动转向一个有权限的试图
                {
Guid id = listSetting.GetCanDisplayView(currentUser);
if (id == Guid.Empty)
{
SPUtility.TransferToErrorPage(Util.GetResource("Msg_NoViewRight"));
return;
}
else
{
SPView view = curList.Views[id];
SPUtility.Redirect( base.Web.Url +"/"+ view.Url, SPRedirectFlags.Default, this.Context);
return;
}
}
SPUtility.TransferToErrorPage(Util.GetResource("Msg_NoViewRight"));
}
//NND, 在2010的07UI模式下这样设置不起作用。
foreach (Control item in base.MenuTemplateControl.Controls)
{
if ((item is MenuItemTemplate))
{
MenuItemTemplate menuItem = (MenuItemTemplate)item;
if (menuItem.PermissionsString != "ViewListItems") //修改视图和创建视图菜单
                    {
menuItem.Visible = false;
continue;
}
try
{
SPView tempView = curList.Views[menuItem.Text];
viewSetting = listSetting.GetByViewName(menuItem.Text);
if (viewSetting == null)
continue;
item.Visible = viewSetting.CanDisplay(currentUser);
}
catch (ArgumentException)
{
}
}
}
}

}
View Code  如何让sharepoint默认使用我们这个PermissionListViewSelector类了,同样我们需要修改ViewSelector模板





<SharePoint:RenderingTemplate ID="ViewSelector" runat="server">
<Template>
<table border=0 cellpadding=0 cellspacing=0 style='margin-right: 4px'>
<tr>
<td nowrap class="ms-listheaderlabel"><SharePoint:EncodedLiteral ID="EncodedLiteral1" runat="server" text="<%$Resources:wss,view_selector_view%>" EncodeMethod='HtmlEncode'/> </td>
<td nowrap class="ms-viewselector" id="onetViewSelector" onmouseover="this.className='ms-viewselectorhover'" onmouseout="this.className='ms-viewselector'" runat="server">
<codeArt:PermissionListViewSelector MenuAlignment="Right" AlignToParent="true" runat="server" id="ViewSelectorMenu" />
</td>
</tr>
</table>
</Template>
</SharePoint:RenderingTemplate>
View Code  最后我们来看看字段权限设置
DSC0007.png
  这里权限设置分为编辑和查看权限,没有编辑权限的用户如下图:
DSC0008.png
  结合权限设置的那张图看一看,这里只有Middle Name字段可以编辑,其他所有字段都不能编辑,Middle Name是允许”ALL User“编辑的,所以这里user可以编辑。查看权限也是一样的。
  这里我们需要开发一个EditControlListFieldIterator类来扩展默认的ListFieldIterator类,如何让sharepoint来使用我们的这些类,我们需要修改sharepoint的ListForm和FileFormFields模板,相关代码如下:





public class EditControlListFieldIterator : Microsoft.SharePoint.WebControls.ListFieldIterator
{
protected override void CreateChildControls()
{
//if (this.ControlMode == SPControlMode.Display)
//{
//    base.CreateChildControls();
//    return;
//}

SPUser currentUser = SPContext.Current.Web.CurrentUser;
if (currentUser != null && currentUser.IsSiteAdmin)
{
base.CreateChildControls();
return;
}
ListFieldPermissionSetting listSetting = ListFieldPermissionSetting.GetListSetting(this.List);
if (listSetting == null || listSetting.Count == 0)
{
base.CreateChildControls();
return;
}
//base.CreateChildControls();
this.Controls.Clear();
if (this.ControlTemplate == null)
{
throw new ArgumentException("Could not find ListFieldIterator control template.");
}
Type t = typeof(TemplateContainer);
PropertyInfo ControlModeProp = t.GetProperty("ControlMode", BindingFlags.Instance | BindingFlags.NonPublic);
PropertyInfo FieldNameProp = t.GetProperty("FieldName", BindingFlags.Instance | BindingFlags.NonPublic);
SPUser author = null;
if (this.ControlMode == SPControlMode.New)
{
author = base.Web.CurrentUser;
for (int i = 0; i < base.Fields.Count; i++)
{
SPField field = base.Fields;
if (!this.IsFieldExcluded(field))
{
FieldPermission set = listSetting.GetByFieldName(field.InternalName);
if (set != null && !set.CanEdit(currentUser, author))
{
continue;
}
TemplateContainer child = new TemplateContainer();
this.Controls.Add(child);
FieldNameProp.SetValue(child, field.InternalName, null);
this.ControlTemplate.InstantiateIn(child);
}
}
}
else
{
SPFieldUserValue authorFieldValue = new SPFieldUserValue(base.Web, "" + this.ListItem["Author"]);
author = authorFieldValue.User;            
for (int i = 0; i < base.Fields.Count; i++)
{
SPField field = base.Fields;
if (!this.IsFieldExcluded(field))
{
SPControlMode thisMode = this.ControlMode;
FieldPermission set = listSetting.GetByFieldName(field.InternalName);
if (set != null )
{
if (!set.CanEdit(currentUser, author))
{
if (set.CanDisplay(currentUser, author))
thisMode = SPControlMode.Display;
else
continue;
}                                
}
TemplateContainer child = new TemplateContainer();
this.Controls.Add(child);
FieldNameProp.SetValue(child, field.InternalName, null);
ControlModeProp.SetValue(child, thisMode , null);
this.ControlTemplate.InstantiateIn(child);
}
}
}
}

}
View Code




<SharePoint:RenderingTemplate ID="ListForm" runat="server">
<Template>
<SPAN id='part1'>
<SharePoint:InformationBar runat="server"/>
<wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop" RightButtonSeparator=" " runat="server">
<Template_RightButtons>
<SharePoint:NextPageButton runat="server"/>
<SharePoint:SaveButton runat="server"/>
<SharePoint:GoBackButton runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
<SharePoint:FormToolBar runat="server"/>
<TABLE class="ms-formtable" style="margin-top: 8px;" border=0 cellpadding=0 cellspacing=0 width=100%>
<SharePoint:ChangeContentType runat="server"/>
<SharePoint:FolderFormFields runat="server"/>            
<codeArt:EditControlListFieldIterator runat="server"/>
<SharePoint:ApprovalStatus runat="server"/>
<SharePoint:FormComponent TemplateName="AttachmentRows" runat="server"/>
</TABLE>
<table cellpadding=0 cellspacing=0 width=100%><tr><td class="ms-formline"><IMG SRC="/_layouts/15/images/blank.gif" width=1 height=1 alt=""></td></tr></table>
<TABLE cellpadding=0 cellspacing=0 width=100% style="padding-top: 7px"><tr><td width=100%>
<SharePoint:ItemHiddenVersion runat="server"/>
<SharePoint:ParentInformationField runat="server"/>
<SharePoint:InitContentType runat="server"/>
<wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbl" RightButtonSeparator=" " runat="server">
<Template_Buttons>
<SharePoint:CreatedModifiedInfo runat="server"/>
</Template_Buttons>
<Template_RightButtons>
<SharePoint:SaveButton runat="server"/>
<SharePoint:GoBackButton runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
</td></tr></TABLE>
</SPAN>
<SharePoint:AttachmentUpload runat="server"/>
<hr/>
</Template>
</SharePoint:RenderingTemplate>
<SharePoint:RenderingTemplate ID="FileFormFields" runat="server">
<Template>
<codeArt:EditControlListFieldIterator runat="server"/>
</Template>
</SharePoint:RenderingTemplate>
View Code  这里我们的权限设置都保存到哪里去了?这里默认是把权限设置的object 序列化为字符串然后保存到一个特定的文档库里面去了的。
DSC0009.png
  看到这个图,我想大家应该知道这里的权限设置时怎么保存的了吧,每个list内容内型权限设置、试图权限设置、字段权限设置分别对应一个文件。
  源码下载
  为了回报大家,这里特地分享一个知识点;大家在安装sharepoint2013 和 VS2013是 一定要保持语言版本一致,我以前遇到一个 站点模板创建后无法识别的issue,原因就是这2个语言不一致。中文版的sharepoint只能识别2052下的自定义模板,而英文版的VS2013 默认会发布到一个1033的文件夹下,所以中文版的sharepoint2013 默认是不能识别英文版VS2013创建的站点模板。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-117902-1-1.html 上篇帖子: 步步为营 SharePoint 开发学习笔记系列 七、SharePoint Timer Job 开发 下篇帖子: Moss/Sharepoint 看RBS如何解决二进制文件的存储(BLOB)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表