solr - Indexing Sitecore Item security and restricting returned search results -
i have several roles defined, each different restrictions content , media items , restrict search results returned based on access rights of logged in user, rather displaying result , user presented "access denied" page. content accessible extranet\anonymous should returned users regardless.
the security follows standard sitecore practices role inheritance (roles within roles) used, need take account also.
i couldn't see in advanced database crawler module , i've looked through sitecore search , indexing guide (version 6.6 , version 7) couldn't find information indexing security applied items. following articles have suggestions:
this feels "dirty" , has potential performance issues, particularly when there large number of items returned. also, (see in comments) issue paging results.
the above looks more realistic, , filter out results based on indexed security roles, there need expand roles handle roles within roles. concern here would need handle denied permissions, when need deny/restrict access roles content items (i know not recommended practice, there specific need deny).
i'm @ planning stage @ moment release of sitecore 7 today there possibility use updated lucene libraries and/or solr if makes life easier - assuming of course of modules webforms marketers , email campaign manager updated before long.
what solutions people using returning search results taking account security? alternatives linked questions above? maybe in sitecore 7 can leverage, updated lucene libraries or solr?
i'd prefer keep "out of box" sitecore , not use other third party search products if @ possible.
a slight alternative suggestion klaus:
in sitecore.contentseach.config you'll find pipeline called contentsearch.getglobalsearchfilters
processors added pipeline applied query, if drop in 1 applies filter based on roles we're good.
computedfield
to start, want computed field added our index configuration:
<fields hint="raw:addcomputedindexfield"> <field fieldname="read_roles" returntype="stringcollection">sitecore.contentsearch.computedfields.readitemroles,sitecore.contentsearch</field> </fields> note stored type collection of strings. we'll use index names of roles can read item.
implementation
we have base abstract class handle extraction of item security details
public abstract class itempermissions: icomputedindexfield { public string fieldname { get; set; } public string returntype { get; set; } public object computefieldvalue(iindexable indexable) { var indexableitem = indexable sitecoreindexableitem; if (indexableitem == null) return null; var security = indexableitem.item.security; return getpermissibles(security); } protected abstract object getpermissibles(itemsecurity security); }we implement above abstracted method
public class readitemroles : itempermissions { protected override object getpermissibles(itemsecurity security) { var roles = rolesinrolesmanager.getallroles(); return roles.where(security.canread).select(r => r.name); } }
note there's performance impact here, reduce indexing speed. reduce impact, add the computed field index configuration index contains secured content. e.g. if web content accessed anonymous user add no benefit.
pipeline
add entry in config
<contentsearch.getglobalsearchfilters> <processor type="sitecore.contentsearch.pipelines.getglobalfilters.applyglobalreadrolesfilter, sitecore.contentsearch" /> </contentsearch.getglobalsearchfilters> implementation
implement pipeline filter check roles of context user
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); } } summary
- create computedfield returns list of valid roles given access right
- apply pipeline processor
contentsearch.getglobalsearchfiltersadd query filter each search request. - use
predicatebuilderclass ensure role names or'ed together
the big benefit here take hit @ index time , handling of item restriction handled through search query normal. no need worry facet numbers or search counts being incorrect.
you can restrict roles checking compute field , can vary application of pipeline filter. can take out pipeline filter , update queries filter when require it.
note biggest problem set requirement re-index content when security restrictions change. should applying security restrictions users themselves, you'll have include additional computed fields.
edit 02/06/2013
i tinkering in project , realised and'ing roles in query. if user had multiple roles assigned both roles have have declared rights item. i've updated pipeline processor use predicatebuilder class or roles. check added ensure predicate not constant, ensures query updated if have filter apply.
Comments
Post a Comment