Après avoir déployé mon site Web sur IIS7.5, j'ai trouvé un comportement étrange: lorsque l'identité du pool d'applications est laissée être ApplicationPoolIdentity
par défaut (comme recommandé dans Identités du pool d'applications IIS ), Ninject
semble être ignoré, car j'obtiens l'erreur suivante lors de la création du tout premier contrôleur:
System.InvalidOperationException: une erreur s'est produite lors de la tentative de création d'un contrôleur de type '..MainController'. Assurez-vous que le contrôleur a un constructeur public sans paramètre. ---> System.DirectoryServices.DirectoryServicesCOMException: Une erreur d'opération s'est produite.
J'ai essayé d'accorder FullAccess
à IIS AppPool\<MySiteAppPool>
dans le dossier contenant le site (y compris tous les sous-dossiers et fichiers), mais cela n'a rien changé.
Cependant, lorsque je définit l'identité du pool d'applications sur n'importe quel compte de domaine (même simple, sans privilèges administratifs, ainsi que sans accès au dossier avec le site), cela fonctionne normalement.
Ninject est installé selon Configuration d'une application MVC tutoriel via le package NuGet.
Je ne suis pas sûr, si c'est pertinent, que le site est censé fonctionner dans un intranet de domaine avec authentification Windows.
Ainsi, le seul problème semble être lié à l'identité du pool d'applications. Pour autant que je souhaite utiliser la méthode recommandée, j'aimerais avoir le ApplicationPoolIdentity
, pas un compte de domaine.
À quoi cela peut-il être lié? Est-il possible de mélanger tout cela ensemble?
Voici un SO avec un problème similaire: ASP.NET MVC 4 + Ninject MVC 3 = Aucun constructeur sans paramètre défini pour cet objet . Cependant, aucune réponse appropriée là à tous non plus.
Comme un commentaire supprimé l'a suggéré, j'ai essayé d'utiliser NetworkSerive
comme identité. Et cela a fonctionné correctement. Cependant, je suppose que ce n'est pas beaucoup mieux qu'un compte de domaine non privilégié.
[~ # ~] modifier [~ # ~]
Soudain, j'ai trouvé une autre dépendance: l'identité du pool d'applications est utilisée pour l'authentification Windows sur le serveur SQL, même si je m'attendais à ce que les informations d'identification de l'utilisateur côté client soient utilisées là-bas.
Basé sur des commentaires
Acceptez qu'un serveur SQL distant soit accessible avec les informations d'identification authentifiées via l'emprunt d'identité.
Cependant, il n'est toujours pas clair quel est le problème avec ApplicationPoolIdentity et Ninject.
L'article mentionné tout en haut de cette question m'a fait supposer que cela pourrait être dû au fait que le compte virtuel n'a pas de profil utilisateur. Cet aspect n'est pas clair pour moi, car on peut toujours activer IIS pour charger le profil utilisateur avec l'attribut LoadUserProfile
. Je ne peux pas obtenir ce qui est IIS va se charger, s'il n'y a pas de profil pour le compte virtuel?
Il y est dit:
IIS ne charge pas le profil utilisateur Windows, mais certaines applications peuvent quand même en profiter pour stocker des données temporaires. SQL Express est un exemple d'application qui fait cela. Cependant, un profil utilisateur doit être créé pour stocker des données temporaires dans le répertoire de profil ou dans le Registre Hive. Le profil utilisateur du compte NETWORKSERVICE a été créé par le système et était toujours disponible. Cependant, avec le passage à des identités de pool d'applications uniques, aucun profil utilisateur n'est créé par le système. Seuls les pools d'applications standard (DefaultAppPool et Classic .NET AppPool) ont des profils utilisateur sur le disque. Aucun profil utilisateur n'est créé si l'administrateur crée un nouveau pool d'applications.
Cependant, si vous le souhaitez, vous pouvez configurer IIS Pools d'applications pour charger le profil utilisateur en définissant l'attribut "LoadUserProfile" sur "true".
J'ai trouvé le fil suivant sur serverfault.com:
Là, il est également indiqué que l'identité du pool d'applications ne peut pas fonctionner en tant que service réseau, en particulier, interroger l'AD.
D'après les détails de la question, cela ressemble beaucoup à un problème d'autorisations provoquant le lancement d'un COMException
, ce qui empêche Ninject d'instancier MainController
. L'exception est liée à System.DirectoryServices
qui sont les classes utilisées pour interroger Active Directory.
Lorsque IIS s'exécute sous les comptes de pool d'applications normaux, ces comptes ne sont pas autorisés à effectuer des requêtes sur Active Directory et un COMException
peut être lancé. Je pense que le message réel dans l'exception (impossible de trouver un constructeur sans paramètre) est un peu un hareng rouge et Ninject essaie de se rabattre sur un autre constructeur puisque le constructeur normal ne fonctionnait pas.
Cela expliquerait pourquoi lorsque vous modifiez le pool d'applications IIS pour qu'il s'exécute en tant que compte de domaine, cela fonctionne soudainement, car ce compte est autorisé à interroger le domaine.
La question de savoir si vous utilisez ou non System.DirectoryServices
vous-même ou si Ninject/IIS/ASP les utilise. Si vous les utilisez vous-même, assurez-vous qu'aucun des constructeurs de vos classes AD ne peut lever d'exceptions (les intercepter et les enregistrer ou quelque chose), ce qui empêchera votre application de se bloquer au démarrage. Vous découvrirez probablement ce que j'ai dit ci-dessus à propos des autorisations.
Si vous avez besoin de IIS pour exécuter en tant que compte de pool d'applications normal (ce qui est une bonne idée) mais toujours interroger AD en tant qu'utilisateur de domaine, vous pouvez spécifier les informations d'identification à DirectoryEntry
et utilisez un DirectorySearcher
pour faire la recherche AD. Si vous êtes sur .Net 4 ou supérieur, je vous recommande d'utiliser le nouveau System.DirectoryServices.AccountManagement
classes à la place (qui vous permettent également de spécifier des informations d'identification).
Avec cette méthode, vous n'aurez pas besoin d'emprunt d'identité pour les requêtes AD et votre pool d'applications peut toujours s'exécuter en tant que comptes de pool d'applications normaux.
les comptes iispool\appPoolName sont appelés comptes virtuels et ont été ajoutés à Windows 2008. L'idée est qu'ils ne sont pas vraiment des comptes au sens propre. Ils permettent une sécurité renforcée entre les processus utilisant le compte de base.
De nombreux services sur votre machine utilisent networkService, un compte intégré avec accès au réseau. De ce fait, si un attaquant devait exploiter l'un de ces services, tout autre processus exécuté sous le même compte serait accessible. Les comptes virtuels, tels que ceux utilisés par IIS empêchent cela en apparaissant en tant que comptes différents, tout en restant le même compte - votre application asp.net fonctionne toujours techniquement en tant que service réseau et accorde à ce compte l'accès à les choses devraient toujours fonctionner. Cela signifie également que si vous avez besoin d'accéder aux ressources réseau, les comptes iispool le feraient comme le fait networkservice et utilisent le compte de domaine des machines.
Si vous accédez à un serveur SQL distant, c'est le compte que vous devez ajouter pour autoriser l'accès à partir de votre serveur Web. Je ne conseillerais pas d'utiliser l'emprunt d'identité, sauf si vous avez vraiment vraiment besoin de voir qui est l'utilisateur sur le serveur SQL. La sécurité de votre application est plus simple si vous la désactivez.
quant à la raison pour laquelle vos injections ne fonctionnent pas, il se peut que l'une de vos dépendances échoue. si controllerA est injecté avec ClassB qui à son tour est injecté avec ClassC et que cette classe ne parvient pas à injecter ClassD, alors toute la chaîne échoue. Je l'ai fait et cela a pris du temps pour réaliser que c'était quelque chose de si éloigné de ce que je regardais.