SharePoint 列表權限控制

一提到sharepoint 我相信權限控制必定會是一個很重要的話題,尤爲是對列表的權限控制,建立、修改、查看權限。其實網上這方面的資料已經不少了,尤爲是如下2篇文章,後來索性把CodeArt_PermissionEx的源代碼下載下來,而後仔細閱讀了如下。html

利用開源SharePoint Permission Extension插件對SharePoint 的列表進行權限控制!ide

經過代碼解決SharePoint列表視圖權限分配問題post

要想徹底明白源碼設計的原理 建議你們先閱讀再議WSS RenderingTemplate 對sharepoint模板覆蓋有一個簡單的瞭解。我把CodeArt_PermissionEx仔細閱讀了一下而且修改了裏面的一些代碼(我的以爲原做者C#基本功通常,sharepoint方面仍是不錯,我這裏修改的是VS2013版的源碼)。修改後部署到sharepoint2013上如圖:ui

內容內型權限設計如圖:this

這裏的PersonType是一個自定義內容內型,每個內型這裏有一我的員和組的權限控制,主要控制user是否能夠新建記錄,好比user不在PersonType內容內型人員和組裏面,那麼這個user將不能建立記錄,沒有權限的user進入後看到的結果如圖:url

看到這裏的新建項目變爲不可用了。spa

這裏說說查找權限的方式,首先咱們須要的咱們的設置保存起來,.net

1)根據咱們的類容類型來找權限設置,若是沒有任何權限設置那麼咱們就直接返回true;插件

2)若是當前用戶是管理員用戶直接返回true;設計

3)在指定的人員裏面查找當前user是否存在,存在返回true;

4)指定的組裏面是否包含當前user,存在返回true;不然返回false

相關代碼以下:

 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的權限設計

沒有權限的人訪問時運行結果以下:

 

這裏的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

 最後咱們來看看字段權限設置

這裏權限設置分爲編輯和查看權限,沒有編輯權限的用戶以下圖:

結合權限設置的那張圖看一看,這裏只有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[i];

                    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[i];

                    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 序列化爲字符串而後保存到一個特定的文檔庫裏面去了的。

看到這個圖,我想你們應該知道這裏的權限設置時怎麼保存的了吧,每一個list內容內型權限設置、試圖權限設置、字段權限設置分別對應一個文件

源碼下載

爲了回報你們,這裏特意分享一個知識點;你們在安裝sharepoint2013 和 VS2013是 必定要保持語言版本一致,我之前遇到一個 站點模板建立後沒法識別的issue,緣由就是這2個語言不一致。中文版的sharepoint只能識別2052下的自定義模板,而英文版的VS2013 默認會發布到一個1033的文件夾下,因此中文版的sharepoint2013 默認是不能識別英文版VS2013建立的站點模板。

相關文章
相關標籤/搜索