none
ASP.NET, contrôle asp:menu - deny RRS feed

  • Question

  • Bonjour.

    Dans une application web écrite en VB 2010, j'utilise un fichier Web.sitemap pour générer mes menus dynamiquement :

    <?xml version="1.0" encoding="utf-8" ?>
    <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
        <siteMapNode url="~/AchTel001.aspx" title="Accueil" description="Accueil du site Téléphonie" roles="*">
          <siteMapNode url="~/AchTel020.aspx" title="Solitaire" description="Page solitaire" />
          <siteMapNode url="~/AchTel021.aspx" title="Andrée" description="Fille aînée" />
          <siteMapNode url="~/AchTel022.aspx" title="Brigitte" description="Première fille cadette">
            <siteMapNode url="~/AchTel024.aspx" title="Coralie qui est l'aînée" description="Petite-fille aînée" />
            <siteMapNode url="~/AchTel025.aspx" title="Denise" description="Petite-fille cadette" />
          </siteMapNode>
          <siteMapNode url="~/Prive/AchTel023.aspx" title="Simone" description="Fille benjamine" />
          <siteMapNode url="" title=""  description="" />
          <siteMapNode url="" title=""  description="" />
        </siteMapNode>
    </siteMap>

    J'ai mis la page AchTel023.aspx dans un sous-dossier Prive, dont je souhaite réserver l'accès à certains utilisateurs (ceux du groupe AD C5290-DL-FSP-FrenchApplicationTeam). À cette fin, j'ai configuré ainsi mon fichier Web.config :

    <?xml version="1.0" encoding="utf-8"?>

    <!--
      Pour plus d'informations sur la configuration de votre application ASP.NET, consultez
      http://go.microsoft.com/fwlink/?LinkId=169433
      -->

    <configuration>
      <configSections>
        ...
      </configSections>
      <location path="Prive">
        <system.web>
          <authorization>
            <allow roles="C5290-DL-FSP-FrenchApplicationTeam" />
            <deny users="*" />
          </authorization>
        </system.web>
      </location>
      <system.web>
        <compilation debug="true" strict="true" explicit="true" targetFramework="4.0" />
        <customErrors mode="Off"/>
        <roleManager
          enabled="true"
          cacheRolesInCookie="true" >
        </roleManager>
        <siteMap defaultProvider="XmlSiteMapProvider" enabled="true">
          <providers>
            <add name="XmlSiteMapProvider"
              description="Default SiteMap provider."
              type="System.Web.XmlSiteMapProvider "
              siteMapFile="Web.sitemap"
              securityTrimmingEnabled="true" />
          </providers>
        </siteMap>
      </system.web>
      <applicationSettings>
        ...
      </applicationSettings>
    </configuration>

    Quand j'exécute mon application sous Visual Studio, tout se passe bien, sauf que le menu ne me propose pas la page AchTel023.aspx, alors que je suis bien membre du groupe AD C5290-DL-FSP-FrenchApplicationTeam. Premier étonnement. Il suffit que je mette en commentairela ligne <deny users="*" /> pour que la page AchTel023.aspx apparaisse à nouveau.

    Quand j'exécute mon application sur un serveur IIS, c'est catastrophique : elle plante après une longue attente avec le message d'erreur suivant :

    A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)
    SQLExpress database file auto-creation error:
    The connection string specifies a local Sql Server Express instance using a database location within the application's App_Data directory. The provider attempted to automatically create the application services database because the provider determined that the database does not exist.

    Ce qui est d'autant plus étonnant que mon application n'utilise pas encore de bases de données ; c'est un web service logé sur un autre serveur qui fait ce travail.

    À nouveau, la simple suppression de la ligne deny fait disparaître le problème.

    Précisions (qui ont un rapport ou pas, je n'en sais rien) : le code suivant ajouté à ma page maître :

                Dim u = HttpContext.Current.User
                Dim b As Boolean = u.IsInRole("C5290-DL-FSP-FrenchApplicationTeam")
                Dim UserRoles() As String = CType(u, RolePrincipal).GetRoles()

    génère sous Visual Studio le résultat suivant : b = False (alors que j'appartient au groupe), et UserRoles.Count=0 (alors que j'appartiens à plusieurs groupes). Sous IIS, l'application plante comme ci-dessus.

    Quelqu'un peut-il l'aider ?

    Merci d'avance,
    Gilbert

    • Déplacé nikhoModerator vendredi 10 juin 2011 08:18 forum cible (Origine :Visual Basic)
    mercredi 8 juin 2011 16:25

Réponses

  • Bonjour,

    les erreurs sql pourraient être du à la présence du nœud <roleManager>. En effet par défaut, si vous configurez votre application pour utiliser des roles cette gestion est effectuée par défaut par le fournisseur AspNetSqlRoleProvider ( c'est la valeur par défaut de l'attribut defaultProvider du noeud roleManager). Ce provider tente de se connecter à une base de données, voir même de la créer si il ne la trouve pas ( d'ou le message d'erreur : The provider attempted to automatically create the application services database because the provider determined that the database does not exist ). Essayer de supprimer ce noeud de votre web.config pour voir si vous avez toujours les erreurs sql.

    Dans votre cas, avez vous vraiment besoin de cette gestion ? J'ai l'impression que votre gestion s'appuie sur des groupes de l'AD et que vous utilisez les logins windows des utilisateurs. Dans ce cas vous devriez donc activer l'authentification windows dans le web.config :

    <authentication mode="Windows"/>
    

    Vous devez aussi vous assurer que cette fonctionnalité authentification windows intégrée est active au niveau de IIS. La démarche exacte dépend de votre version de IIS. Quelle version de IIS utilisez vous ?

    Par ailleurs quand vous testez le user pour savoir si il appartient à un groupe de l'active directory vous devriez indiquer le nom du domaine :

    Dim b As Boolean = u.IsInRole("MONDOMAINE\C5290-DL-FSP-FrenchApplicationTeam")
    

    Effectuer ces modifications et tenez nous au courant des résultats.

    Cordialement

     

     

     

    mercredi 8 juin 2011 17:15
    Modérateur

Toutes les réponses

  • Bonjour,

    les erreurs sql pourraient être du à la présence du nœud <roleManager>. En effet par défaut, si vous configurez votre application pour utiliser des roles cette gestion est effectuée par défaut par le fournisseur AspNetSqlRoleProvider ( c'est la valeur par défaut de l'attribut defaultProvider du noeud roleManager). Ce provider tente de se connecter à une base de données, voir même de la créer si il ne la trouve pas ( d'ou le message d'erreur : The provider attempted to automatically create the application services database because the provider determined that the database does not exist ). Essayer de supprimer ce noeud de votre web.config pour voir si vous avez toujours les erreurs sql.

    Dans votre cas, avez vous vraiment besoin de cette gestion ? J'ai l'impression que votre gestion s'appuie sur des groupes de l'AD et que vous utilisez les logins windows des utilisateurs. Dans ce cas vous devriez donc activer l'authentification windows dans le web.config :

    <authentication mode="Windows"/>
    

    Vous devez aussi vous assurer que cette fonctionnalité authentification windows intégrée est active au niveau de IIS. La démarche exacte dépend de votre version de IIS. Quelle version de IIS utilisez vous ?

    Par ailleurs quand vous testez le user pour savoir si il appartient à un groupe de l'active directory vous devriez indiquer le nom du domaine :

    Dim b As Boolean = u.IsInRole("MONDOMAINE\C5290-DL-FSP-FrenchApplicationTeam")
    

    Effectuer ces modifications et tenez nous au courant des résultats.

    Cordialement

     

     

     

    mercredi 8 juin 2011 17:15
    Modérateur
  • Bonjour Nikho.

    Merci pour ta réponse, grâce à laquelle les choses vont beaucoup mieux.

    J'ai supprimé le noeud <roleManager> et les ennuis ont disparu. En fait, j'avais ajouté ce noeud après avoir lu la page http://msdn.microsoft.com/fr-fr/library/5k850zwb.aspx. Sans doute ai-je mal compris quelque chose en la lisant.

    La présence de la ligne <authentication mode="Windows"/> ne change rien ; peut-être parce que ce site avait déjà été configuré dans IIS pour n'accepter que l'authentification Windows.

    Quant au nom de domaine pour préfixer le nom de groupe AD, c'est facultatif. Cela fonctionne aussi bien avec que sans.

    Reste un problème : l'instruction CType plante :

    Dim u = HttpContext.Current.User
    Dim UserRoles() As String = CType(u, RolePrincipal).GetRoles()
    

    depuis que j'ai supprimé le noeud <roleManager> :

    Impossible d'effectuer un cast d'un objet de type 'System.Security.Principal.WindowsPrincipal' en type 'System.Web.Security.RolePrincipal'.

    Donc il reste une question : est-il possible d'obtenir la liste des groupes AD auquel appartient un utilisateur, sans pour autant programmer une lecture avec System.DirectoryServices ?

    Cordialement,

    Gilbert

    jeudi 9 juin 2011 08:55
  • Via authentification windows l'identité est effectivement gérer par les classes WindowsPrincipal et WindowsIdentity et n'avez plus alors accès à la méthode GetRole. Vous devez donc modifier votre cast :

    Dim winPrincipal As WindowsPrincipal = CType(HttpContext.Current.User, WindowsPrincipal)
    Dim b As Boolean = winPrincipal.IsInRole("MonDomaine\MonGroup")
    

    Reste qu'en fonction de la déclaration des rôles dans l'AD la méthode ne retourne pas toujours la valeur attendue...Est ce correct pour vos groupes ?

    Cordialement

    jeudi 9 juin 2011 09:38
    Modérateur
  • Le fait de transtyper HttpContext.Current.User en WindowsPrincipal apporte le même résultat que sans transtypage : je récupère le domain\userid, et la méthode IsInRole renvoie le bon résultat (au moins pour les users et les groupes que j'ai testés).

    Je comprends d'autre part que je ne peux pas obtenir par une classe User la liste des groupes AD dont le userid est membre, et qu'il me faut nécessairement déclencher une lecture avec System.DirectoryServices.

    Merci pour votre aide.

    Gilbert

    jeudi 9 juin 2011 10:19
  • En passant par WindowsIdentity on doit pouvoir s'affranchir de coder la lecture nous même sur l'AD.

    Dim winPrincipal As WindowsPrincipal = CType(HttpContext.Current.User, WindowsPrincipal)
    
    Dim irc As IdentityReferenceCollection = DirectCast(winPrincipal.Identity, WindowsIdentity).Groups.Translate(Type.GetType("System.Security.Principal.NTAccount"))
    
    

    On peut alors boucler dessus

    For Each acc As NTAccount In irc
    
    Next
    
    On trouve aussi des exemple utilisations la reflexion mais pour ma part il ne fonctionnait pas...

    Cordialement

     

     

     

    jeudi 9 juin 2011 12:59
    Modérateur
  • Ça fonctionne parfaitement.

    Mais comment peut-on avoir appris tout ça !

    Bonne journée,

    Gilbert

    jeudi 9 juin 2011 13:42