[.NET] Appeler un objet COM tout en conservant l’impersonation
Voila une problématique que j’ai rencontré récemment et qui n’est pas aussi simple à régler que ce que l’on pourrait penser. Imaginer que l’on vous demande d’appeler un objet COM (tel que Analysis Services, au moyen de Microsoft.AnalysisServices.AdomdClient) mais qu’on vous impose de faire de l’impersonation (dans un service WCF par exemple) pour que vous puissiez tracer qui exécute la requête MDX.
Ni une, ni deux: vous mettez en place l’impersonation dans votre service WCF. Ainsi, vous commencez par rajouter cette ligne dans votre fichier web.config:
1: <identity impersonate="true" />
Puis, dans votre code, vous récupérer l’Identity de l’utilisateur courant et vous appelez la méthode Impersonate:
1: if (HttpContext.Current != null)
2: {
3: if (HttpContext.Current.User != null)
4: {
5: if (HttpContext.Current.User.Identity != null)
6: {
7: IIdentity identity = HttpContext.Current.User.Identity;
8: WindowsIdentity windowsIdentity = identity as WindowsIdentity;
9: if (windowsIdentity != null)
10: {
11: using (WindowsImpersonationContext wiCtx = windowsIdentity.Impersonate())
12: {
13: // Call to Analysis Services here
14: }
15: }
16: }
17: }
18: }
Vous exécutez votre code et là, en traçant les requêtes, vous vous apercevez que c’est un compte système qui exécute les requêtes: il semble donc y avoir un problème avec votre impersonnation…
En fait, il s’avère que votre code est correct. Le problème, expliqué ici, réside dans le fait que les objets COM utilise un modèle de thread STA (Single Thread Apartment) alors que votre service WCF, en .NET, utilise un modèle de thread MTA (Multithread Apartment). Si vous voulez connaitre la différence, jetez donc un oeil ici: http://stackoverflow.com/questions/127188/could-you-explain-sta-and-mta
Pour résoudre notre problème, la solution est simple: il suffit de créer un nouveau thread et de lui imposer de tourner en STA 
1: theThread = new Thread(new ThreadStart(MySTAThreadStart));
2:
3: // Intialize to an STA so that there will be no thread switch to the STA COM object.
4: theThread.ApartmentState = ApartmentState.STA;
A partir de là, votre code appelera l’objet COM (Analysis Services) avec un modèle de thread STA ce qui permettra de conserver l’impersonnation !
Voila qui, je l’espère, permettra de gagner pas mal de temps à certains d’entre vous 
A+
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :