2006-04-18

Använd AppDomains när SharePoints OM inte tillåter impersonering

Det är lustigt hur de enklaste problem ibland kan kräva extraordinära insatser för att gå runt. SharePoints objekt­modell har ett underligt beteende – kalla det bugg eller finess – som gör att impersonering i vissa sammanhang inte fungerar för vissa metoder. Orsaken till beteendet är att SharePoint tar identiteten från HttpContext och struntar i om man har impersonerat eller ej. Detta gäller bara då koden exekverar i en webb­applikation, eller i en webpart. Konsol­applikationer eller windows­applikationer berörs inte. Så har det sett ut sen SharePoint 2003 RTM, och gäller fortfarande för SP2.

Det kan vara frustrerande när så enkel kod som SPControl.GetContextWeb(Context).Webs.Count; resulterar i att alla Readers får se inloggningsruta efter inloggningsruta, och till slut den berömda Request Access-sidan, trots att du tagit i till max och impersonerat MYSERVER\Administrator. *Pust*. Du kan i och för sig hindra inloggnings­rutorna från att visas genom att sätta CatchAccessDeniedException till false och sen fånga System.UnauthorizedAccessException och visa ditt eget felmeddelande, som beskrivs här och här, men det löser inte ursprungs­problemet.

Men vad säger Microsoft om det här? Felet är känt och noterat, men ingen åtgärd för tillfället. De skriver om det i KB 892866, och jag gillar speciellt formuleringen där de benämner buggen som "functionality":
Impersonation is not currently supported in some elements of the SharePoint Portal Server object model or in some elements of the Windows SharePoint Services object model. This functionality is being investigated for future versions of the object models.
Så långt problembeskrivning, men hur kommer man runt det?

Lösningen är helt enkelt att se till att det inte finns någon HttpContext att plocka "fel" identitet från. Ett sätt att gömma sin HttpContext är att exekvera den impersonerade koden i en annan AppDomain. Man kan säga att en AppDomain är för CLR vad en process är för Win32, fast mer lättvikt med lägre overhead. Så här går det till i grova drag.
  1. Impersonera, eller gör RevertToSelf till processkontot.
  2. Skapa en ny AppDomain.
  3. Exekvera koden (ex SPWeb.Roles[]) i din nya AppDomain.
  4. Skicka tillbaks resultat.
  5. Avsluta din AppDomain.
  6. Återgå från impersonerad identitet till rätt identitet.
Ganska enkelt på pappret, men kräver en hel hög med kod och tungan i rätt mun. Här är ett par artiklar som ger alla detaljerna. Se till att du läser kommentarerna också.Ganska mycket kodning för att komma runt en bugg, men alltid lär man sig något nytt på vägen. Den här tekniken är intressant eftersom den använder AppDomains, men det finns också andra lösningar som jag återkommer till.

Technorati tags: , ,

0 Comments:

Skicka en kommentar

Links to this post:

Skapa en länk

<< Home