首先声明这个领域小弟也是刚涉足, 经验浅的很. 一些看法和说法都是卑微之语. Windows Sharepoint Server中的权限(Authorization)设置是通过中间件角色(Role)来与指定用户(User)发生关系的. 并不如同传统的直接给予某个用户相应的权限. 即应该通过创建一个角色然后在其中组合不同的权限最后将一个角色赋予一个用户. 用户组的概念也是如此. User/Group -- Role --Authorization
无论当你是将一个用户或者组添加入对于某个列表或者某个文件中获得相应的权限. 那些关于用户和用户组的信息分配存放在配置数据库的UserInfo和Groups表中. 其中tp_siteId代表了所属站点的ID, tp_Id则是分配给用户的ID, Groups的组织方式也基本和UserInfo差不多. Role 即角色表, 存放所创建的角色. RoleAssignment存放角色的分配. 其中的ScopeId 会对应Perms表中的ScopeId, 当你为一个列表或者某个文件添加权限时并且不继承父权限的时候, 在Perms表中会添加相应的新记录内容, 并且创建它的ScopeUrl与ScopeID来标识它. 并且与RoleAssignment中的scopeId对应, 而RoleAssignment中的PrincepalId则存放对应的UserInfo中的tp_Id或者Groups中的tp_Id. 两张表中的tp_Id是不会重复的. 搞清楚了权限组合和角色创建与分配是如何组成的. 现在来看一下如何通过Windows Sharepoint Server的对象模型以编程方式解决一些问题. 比如我想通过一个EventHandler当用户上传某个文件以后让他选择相应的本地域中已存的AD帐户.
实现Windows Sharepoint Server的EventHandler有两种方式(暂时只了解两种), 一种是实现IListEventSick接口. 这种方式的缺点暂时令我感觉到的是很难做一些更复杂的操作. 另一种方式是派生相应的操作时间类. 如果是一些内容则是SPItemEventReceiver. 具体内容可以通过Reflector反射Microsoft.Sharepoint.dll了解. 可以重写其中的实现方法来实现我们需要的功能. 现在要编写一个添加完Item后执行的权限分配操作. 也就是当用户在文档中心上传完一个文件以后, 将一个指定的用户添加入其中获得该文件的相应权限.
public override void ItemAdded(SPItemEventProperties properties){}
通过SPItemEventProperties我们可以获得不少关于触发事件的Item的信息. 如SiteId(站点ID), ListId(列表ID), ListItemId(列表项ID). 比如我要访问那个刚上传文档的对象可以通过以下方式:
SPSite sourceSite = new SPSite(properties.SiteId);
SPWeb sourceWeb = sourceSite.OpenWeb();
SPListItem currentListItem = sourceWeb.Lists[properties.ListTitle].Items.GetItemById(properties.ListItemId);
每个列表条目都提供一个角色分配集合RoleAssignments属性, 它是一个Collection. 提供基本的操作方法. 利用Add我们则可以添加相应的新的RoleAssignment元素.
我们通过建立一个RoleAssignment的实例来添加用户:
SPRoleAssignment roleAssignment = new SPRoleAssignment(sourceWeb.EnsureUser(SHBEYONDBIT\chujun));
SPRoleDefinition roleDefinition = sourceWeb.RoleDefinitions.GetByType(SPRoleType.Read);
SPRoleType 是一个enum提供默认角色级别
SPRoleType.Administrator = 完全控制
SPRoleType.WebDesigner = 设计
SPRoleType.Contributor = 参与讨论
SPRoleType.Reader = 读取
SPRoleType.Guest = 受限访问
SPRoleType.None = 仅查看
对于我们自己创建的Role则不提供支持. 我们需要通过其它方式来获得. 通过RoleDefinitionBindings属性的Add方法我们添加了一个Role给予指定的用户.
roleAssignment.RoleDefinitionBindings.Add(roleDefinition);
currentListItem.BreakRoleInheritance(false);
BreakRoleInheritance就如同我们手动设置用户角色时选择的是否不在继承父权限一样. 我们不再继承父权限. 最后通过currentListItem.RoleAssignments.Add(roleAssignment); 为相应列表添加了某个用户的角色.
在这里有一点令人有些费解, 起初我并非用EnsureUser方法实现用户添加的, 而是通过SPUserInfo创建一个实例. 将AD帐号的一些信息写入其中. 然后通过sourceWeb.User.Add方法来实现添加, 可惜屡屡报错说当前状态无效. 不知有哪位高人知道为何? 不吝赐教.
现在在来讨论关于如何自定义角色问题. 在Windows Sharepoint Server中提供了相当多的权限. 并且通过SPBasePermissions这个enum来设定. 其实实现的方式大致应该是一个int类型. 然后相应的位放置1来确定吧. 即以一个unsigned short为例 00100100可能代表某个Role拥有未知的两个权限.
SPRoleDefinition definition = new SPRoleDefinition(); 创建角色定义的实例.
public bool AddSiteRole(string name, string description, params SPBasePermissions[] args){
bool flag = true;
SPRoleDefinition definition = new SPRoleDefinition();
definition.Name = name;
definition.Description = description;
foreach (SPBasePermissions arg in args){
definition.BasePermissions |= arg;
}
try{
_sourceWeb.RoleDefinitions.Add(definition);
}
catch{
flag = false;
}
return flag;
}
进行相应位置的|操作就可以分配相应的权限了. 如下:
AddSiteRole("自定义角色1", "自定义角色1", SPBasePermissions.AddAndCustomizePages, SPBasePermissions.AddDelPrivateWebParts, SPBasePermissions.AddListItems, SPBasePermissions.ApplyStyleSheets);
顺带一提, 因为SPUser和SPGroup都派生于SPPrincipal, 而SPRoleAssignment可以接受任何派生与SPPrincipal的类型进行添加. 想想之前数据表RoleAssignment表中的PrincepalId, 在真挺有逻辑的.
最近有一个项目是针对基于Windows Sharepoint Server, 并利用Microsoft Office Sharepoint Server2007和Design的开发和部署(其实我对这个项目是颇有微辞的, 首先对于这类技术的集成还没有掌握, 项目书上说是配置占70%以上, 其实不然以这样的要求显然开发占了70%以上). 并且我对这种Microsoft极度推崇的技术也是心存一些不满的. 首先它的内容更广一些,不仅设计了Windows WorkFlow Fundation, Web Part, ASP.NET 2.0, CAML, Infopath以及Windows Sharepoint Server等大量内容还有许多企业应用的概念. 并与Office系列产品有高度集成. 这对于一个开发人员来说需要掌握更多的技术特性. 其实光是精通其中两样已经是很不容易的一回事了. 基于它的二次开发难度较大, 并且许多默认提供用户的操作方式都不是传统的Web用户操作习惯. 说穿了只是Microsoft想要捆绑它的一整套产品销售, 卖给那些政府或者大型企业而已. 哎! 感叹做为开发人员, 不是每个项目都能选择让你使用你擅长的喜爱的技术.
不知道有谁会在上传完文件以后先不跳往那个定义名字和注释的页面, 而是跳往我想指定的页面. 因为在Windows Sharepoint Server的那些上传之类的都是以做完的模板, 可能有些按钮时间是自定义的控件. 比如像那些SPWikiButton一类. 以完全将处理方法封装起来了. 除非直接修改页面上脚本. 但是这类都是模板无法如同那些其它的Default.aspx或者Default.Master那样进行修改. 而也无法获得所谓的窗体句柄. 如有实现方式请不吝赐教.