对 Klaus 的建议稍作替代:
在Sitecore.ContentSeach.config
你会发现一个名为的管道contentSearch.getGlobalSearchFilters
添加到此管道的处理器将应用于任何查询,因此如果我们加入一个基于角色应用过滤器的处理器,我们就很好了。
计算场
首先,我们希望将一个计算字段添加到我们的索引配置中:
<fields hint="raw:AddComputedIndexField">
<field fieldName="read_roles" returnType="stringCollection">Sitecore.ContentSearch.ComputedFields.ReadItemRoles,Sitecore.ContentSearch</field>
</fields>
注意存储的类型是字符串的集合。我们将使用它来索引可以读取项目的所有角色名称。
执行
我们有一个基础抽象类来处理项目安全细节的提取
public abstract class ItemPermissions: IComputedIndexField
{
public string FieldName { get; set; }
public string ReturnType { get; set; }
public object ComputeFieldValue(IIndexable indexable)
{
var indexableItem = indexable as SitecoreIndexableItem;
if (indexableItem == null) return null;
var security = indexableItem.Item.Security;
return GetPermissibles(security);
}
protected abstract object GetPermissibles(ItemSecurity security);
}
我们用抽象的方法来实现上面的
public class ReadItemRoles : ItemPermissions
{
protected override object GetPermissibles(ItemSecurity security)
{
var roles = RolesInRolesManager.GetAllRoles();
return roles.Where(security.CanRead).Select(r => r.Name);
}
}
注意这里显然会对性能产生影响,这会降低您的索引速度。为了减少影响,仅将计算字段添加到包含安全内容的索引的索引配置中。例如,如果您的 Web 内容仅由匿名用户访问,则不会带来任何好处。
管道
将条目添加到配置中
<contentSearch.getGlobalSearchFilters>
<processor type="Sitecore.ContentSearch.Pipelines.GetGlobalFilters.ApplyGlobalReadRolesFilter, Sitecore.ContentSearch" />
</contentSearch.getGlobalSearchFilters>
执行
实现管道过滤器以检查上下文用户的角色
public class ApplyGlobalReadRolesFilter : GetGlobalFiltersProcessor
{
public override void Process(GetGlobalFiltersArgs args)
{
var query = (IQueryable<SitecoreUISearchResultItem>)args.Query;
var userRoles = Context.User.Roles.Select(r => r.Name.Replace(@"\", @"\\"));
var predicate = PredicateBuilder.True<SitecoreUISearchResultItem>();
predicate = userRoles.Aggregate(predicate, (current, role) => current.Or(i => i["read_roles"].Contains(role)));
if(predicate.Body.NodeType != ExpressionType.Constant)
args.Query = query.Filter(predicate);
}
}
概括
- 创建一个返回给定访问权限的所有有效角色列表的 ComputedField
- 应用管道处理器
contentSearch.getGlobalSearchFilters
为每个搜索请求添加查询过滤器。
- 使用
PredicateBuilder
类来确保角色名称是 OR'ed 在一起
这里最大的好处是您在索引时受到打击,并且项目限制的处理是通过搜索查询正常处理的。无需担心构面编号或搜索计数不正确。
您可以限制要检查的角色来计算字段,并且可以改变管道过滤器的应用程序。您甚至可以取出管道过滤器,并在需要时更新您的查询以进行过滤。
注意 此设置的最大问题是需要在安全限制更改时重新索引您的内容。如果您对用户本身应用安全限制,则必须包含额外的计算字段。
编辑 02/06/2013
我只是在一个项目中对此进行了修补,并意识到它正在查询中的角色。如果用户分配了多个角色,那么这两个角色都必须声明对该项目的权限。我已经更新了管道处理器以使用PredicateBuilder
该类来 OR 角色。还添加了一项检查以确保谓词不是常量,这确保仅当我们有要应用的过滤器时才更新查询。