none
Permessi utente su webpart RRS feed

  • Domanda

  • Ho creato una visual webpart in cui visualizzo qualche label e una lista. Ho poi importato la webpart in una pagina vuota.

    Tutto funziona correttamente: loggando col mio account, che appartiene al gruppo "[Site collection name] Owners", riesco a vedere il tutto; ma se loggo come un altro utente, ad esempio un utente che appartiene al gruppo "[Site collection name] Visitors", non riesco ad accedere alla pagina con la webpart, e mi da sto errore: Error: Access denied - you are currently signed in as: XXX

    E' normale che mi faccia così? Dove devo impostare i permessi della webpart?

    • Modificato MMaik mercoledì 20 ottobre 2010 10:26
    martedì 19 ottobre 2010 14:20

Risposte

  • Ciao !
    Il permesso "contribute" non basta neanche, ci vuole "design" almeno per modificare la struttura di una lista.

    Però per fare in modo che il tuo codice venga eseguito con privilegi amministrativi e lasciare i permessi degli utenti a "read" devi impersonificare il tuo codice. Questo si può fare utilizzando il metodo RunWIthEvelatedPrivileges della classe SPSecurity.

    Trovi un esempio d'uso qua:
    http://www.peppedotnet.it/Blog/HowToUseRunWithElevatedPrivilegesMethod.aspx

    Ricordati solo di non prendere MAI le istanze di alcuni oggetti SharePoint dal contesto di SharePoint stesso, ma istanziale sempre nuove. Questo vale per gli oggetti SPSite e SPWeb. Quindi NON usare la sintassi SPWeb web = SPContext.Current.Web, altrimenti l'impersonazione non funziona.


    Giuseppe Marchi - SharePoint MVP
    www.peppedotnet.it
    www.dev4side.com
    www.sharepointcommunity.it
    Twitter: @PeppeDotNet
    • Contrassegnato come risposta MMaik mercoledì 20 ottobre 2010 11:53
    mercoledì 20 ottobre 2010 10:50

Tutte le risposte

  • Ciao !
    Ma questa web part che cosa fa ?
    Perchè sono le operazioni che fai in questa web part a darti l'errore di accesso. Magari l'accesso a qualche lista dove il secondo utente non ha permessi, o simile..


    Giuseppe Marchi - SharePoint MVP
    www.peppedotnet.it
    www.dev4side.com
    www.sharepointcommunity.it
    Twitter: @PeppeDotNet
    martedì 19 ottobre 2010 14:23
  • Ciao Giuseppe
    Ho fatto un po di debugging e ora so dire esattamente dove la webpart si blocca
    Quell'errore (Error: Access denied - you are currently signed in as: XXX) mi esce quando eseguo il comando:

    docview.Update(); 
    

    in pratica quando tento di modificare una view di una lista (docview è il nome della vista)
    Quindi deduco che applicare le modifiche ad una vista è un operazione che richiede un permesso quantomeno "contribute". Eppure io avrei bisogno di tenere a livello "read" i permessi di questo utente per quella lista.
    Esiste una soluzione a questa situazione?

    mercoledì 20 ottobre 2010 09:19
  • Ciao !
    Il permesso "contribute" non basta neanche, ci vuole "design" almeno per modificare la struttura di una lista.

    Però per fare in modo che il tuo codice venga eseguito con privilegi amministrativi e lasciare i permessi degli utenti a "read" devi impersonificare il tuo codice. Questo si può fare utilizzando il metodo RunWIthEvelatedPrivileges della classe SPSecurity.

    Trovi un esempio d'uso qua:
    http://www.peppedotnet.it/Blog/HowToUseRunWithElevatedPrivilegesMethod.aspx

    Ricordati solo di non prendere MAI le istanze di alcuni oggetti SharePoint dal contesto di SharePoint stesso, ma istanziale sempre nuove. Questo vale per gli oggetti SPSite e SPWeb. Quindi NON usare la sintassi SPWeb web = SPContext.Current.Web, altrimenti l'impersonazione non funziona.


    Giuseppe Marchi - SharePoint MVP
    www.peppedotnet.it
    www.dev4side.com
    www.sharepointcommunity.it
    Twitter: @PeppeDotNet
    • Contrassegnato come risposta MMaik mercoledì 20 ottobre 2010 11:53
    mercoledì 20 ottobre 2010 10:50
  • Grandissimo!
    Sono riuscito a risolvere il tutto in questo modo:

      public partial class VisualWebPart1UserControl : UserControl
      {
        bool security = false;
        protected void Page_Load(object sender, EventArgs e)
        {
          using (SPSite site = new SPSite("http://dev_seventeen:999"))
          {
            using (SPWeb web = site.OpenWeb())
            {
              if (web.DoesUserHavePermissions(SPBasePermissions.FullMask))
              {
                security = true;
              }
              SPSecurity.RunWithElevatedPrivileges(mioMetodo);
            }
          }
        }
    
        public void mioMetodo()
        {
          if (security)
          { ... }
        }
      }
    
    Così la pagine è accessibile indipendentemente dall'utente che logga, ma attraverso il bool security posso comunque controllare il suo livello di permessi e nascondere alcune parti della pagina =)

    Grazie!
    mercoledì 20 ottobre 2010 11:52
  • Figurati ! ;)

    A presto
    Peppe


    Giuseppe Marchi - SharePoint MVP
    www.peppedotnet.it
    www.dev4side.com
    www.sharepointcommunity.it
    Twitter: @PeppeDotNet
    mercoledì 20 ottobre 2010 12:00
  • Ahi ahi, due bachi in una riga sola...

     public partial class VisualWebPart1UserControl : UserControl
      {
        bool security = false;
        protected void Page_Load(object sender, EventArgs e)
        {
          using (SPSite site = new SPSite(http://dev_seventeen:999))

    1) Non ti serve ricreare il contesto SPSite al caricamento della Web Part potresti usare SPcontext;
    2) Stai ricreando un contesto SPSite con l'identità dell'utente corrente che non è detto che abbia l'autorizzazione di System Account per modificare la view....il contesto cosi creato sarebbe identico a quello che SPcontext ti fornirebbe.

    Nell'esempio d'uso di Peppe su RunWithElevatedPrivileges è chiaro che DEVI ricreare il contesto DENTRO il delegate RunWithElevatedPrivileges e non fuori.

    mercoledì 20 ottobre 2010 12:02
  • Oddio non ho capito bene cosa intendi Gabriele

    Comunque nel codice non ho indicato un frammento che in effetti è di fondamentale importanza. Rifaccio daccapo:

    public partial class VisualWebPart1UserControl : UserControl
     {
      bool security = false;
      protected void Page_Load(object sender, EventArgs e)
      {
       using (SPSite site = new SPSite("http://dev_seventeen:999"))
       {
        using (SPWeb web = site.OpenWeb())
        {
         if (web.DoesUserHavePermissions(SPBasePermissions.FullMask))
         {
          security = true;
         }
         SPSecurity.RunWithElevatedPrivileges(mioMetodo);
        }
       }
      }
    
      public void mioMetodo()
      {
        using (SPSite site = new SPSite("http://dev_seventeen:999"))
        {
          using (SPWeb web = site.OpenWeb())
          {
            ...
            if (security)
            { ... }
            ...
           }
         }
       }
     }
    
    

    In pratica devo usare due volte SPSite e SPWeb: una volta all'esterno per poter andare a settare il bool security (per il quale devo avere l'SPWeb su cui chiamarci il .DoesUserHavePermission), ed una volta all'interno per farci tutte le operazioni su liste ecc

    Devo per forza fare così o sbaglio?

    mercoledì 20 ottobre 2010 12:15
  • mioMetodo() va bene cosi, crei il contesto NEL delegate.

    E' la ricreazione del contesto nel page_load della WebPart che non serve a niente se agisci su cose che stanno nello stesso Web in cui la web part si trova, secondo me eh....

    Poi quell url fisse mi fanno venire i brividi.... 

    mercoledì 20 ottobre 2010 12:25
  • Anche a me sembra un po strano come ho sistemato la cosa... il problema è che la ricreazione del contesto nel page_load mi serve per capire se l'utente ha i permessi o no. Perchè se questo controllo lo faccio all'interno di mioMetodo otterrò sempre una risposta positiva in quanto ho elevato i permessi dell'utente.

    Sennò non saprei come fare... hai un esempio?

    mercoledì 20 ottobre 2010 12:30
  • Allora, se tu devi fare delle operazioni che richiedono l'impersonificazione la creazione di un SPSite prima del delegate non serve.
    Non serve se tutto il tuo codice va impersonato.

    Se invece, prima di fare le operazioni su SharePoint che richiedono permessi di amministratore, devi controllare che effettivamente l'utente corrente possa o non possa accedere a qualche altro oggetto SharePoint (nel tuo caso, altre operazioni differenti dalla creazione della vista), allora utilizzare un SPSite o un SPWeb prima del RunWithElevatedPrivileges è corretto.
    Però, se sei in questo secondo caso, allora è meglio prendere il sito SharePoint dal contesto (SPContext.Current.Web).

    Spero di essermi spiegato.

    Come dice Gab poi, è meglio non codificare le url direttamente nel codice..


    Giuseppe Marchi - SharePoint MVP
    www.peppedotnet.it
    www.dev4side.com
    www.sharepointcommunity.it
    Twitter: @PeppeDotNet
    mercoledì 20 ottobre 2010 12:40
  • Mi sembra tutto così maledettamente complicato... abbiate pazienza ma ho iniziato a programmare da sole 3 settimane =(

    Scusate l'ignoranza, ma come dovrei passargli le url?

    Comunque Peppe mi sa che il mio caso è proprio quello del secondo tipo, perchè oltre a modificare la vista devo anche far vedere dei dati attraverso delle label, e questo in base ai permessi dell'tente che consulta il sito (solo l'amministratore può vedere alcune cose in pratica)
    Però in tutta onestà non ho capito bene che differenza c'è tra ottenere l'SPWeb con SPContext.Current.Web ed ottenerlo con SPSite("url") e poi site.OpenWeb().
    Perchè dite che nel page load è meglio il primo metodo mentre in "mioMetodo" è meglio il secondo?

    mercoledì 20 ottobre 2010 12:53
  • se tu vuoi ottenere le informazioni da sharepoint in base ai permessi dell'utente corrente, hai già delle istanze delle classi SPWeb e SPSite che puoi utilizzare. queste le puoi prendere dal contesto corrente tramite la classe SPContext.

    SPWeb webInUserContext = SPContext.Current.Web;
    Console.Writeline("Utente corrente: {0}", webInUserContext.CurrentUser.Name);
    

     

    Se invece devi impersonare, NON puoi prendere le istanze delle classi SPSite e SPWeb dal contesto dell'utente corrente perchè così facendo NON funziona la chiamata al metodo RunWithElevatedPrivileges.
    Quindi, all'interno del delegato referenziato da questo metodo, è necessario istanziare dei nuovi oggetti di tipo SPSite e SPWeb, così le informazioni che prendi da queste ultime saranno le stesse che vede un amministratore.

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
      SPSite site = new SPSite("url");
      using(site)
      {
       SPWeb web = site.OpenWeb();
       //azioni eseguite nel contesto dell'amministratore
      }
    });

    Giuseppe Marchi - SharePoint MVP
    www.peppedotnet.it
    www.dev4side.com
    www.sharepointcommunity.it
    Twitter: @PeppeDotNet
    mercoledì 20 ottobre 2010 13:04
  • Tutto chiaro, grazie per le delucidazioni

    Riguardo alle url invece? C'è un modo per ottenerle via codice senza doverle mettere manulmente o come?

    mercoledì 20 ottobre 2010 13:30
  • Per al gestione automatica delle url, hai diverse modalità (ti scrivo quelle che mi vengono in mente):

    1. Puoi creare una proprietà nella tua web part in cui inserire poi l'url tramite interfaccia grafica
    2. Puoi prenderla dalla proprietà Page.Request.Url (attenzione però a prenderla prima di impersonificare)
    3. Puoi inserire l'url nel web.config della tua web application e leggerlo poi da li (non bellissima però funziona)

    A presto

    Peppe


    Giuseppe Marchi - SharePoint MVP
    www.peppedotnet.it
    www.dev4side.com
    www.sharepointcommunity.it
    Twitter: @PeppeDotNet
    mercoledì 20 ottobre 2010 15:35
  • Prelevarle dal contesto?
    mercoledì 20 ottobre 2010 16:30