Cambiar las credenciales de usuario en Sharepoint

En ocasiones puede plantearse el caso en el que necesitemos manejar los objetos de Sharepoint pero con una identidad distinta a la del usuario logado o el del administrador.

Dentro del contexto de Sharepoint disponemos de varios métodos para cambiar las credenciales:

RunWithElevatedPrivileges

Requiere de Impersonate=true

SPSecurity.RunWithElevatedPrivileges( delegate() {

….

} );

 

WindowsImpersonationContext

Nos permite ejecutar nuestro código con las credenciales de otro usuario. En este ejemplo con el usuario configurado en el pool de aplicaciones:

using (WindowsImpersonationContext wic = WindowsIdentity.Impersonate(IntPtr.Zero))

{

………….

}

 

SHAREPOINT\system

Consiste en capturar el Token del usuario “system” para conectar de nuevo con ese token.

El usuario “SHAREPOINT\system” es un usuario especial, utilizaremos este caso cuando nos encontremos en un EventReceiver ya que no podremos utilizar RunWithElevatedPrivileges.

using (SPWeb webOrigUser = properties.OpenWeb())
{
    SPUserToken token = webOrigUser.AllUsers[«SHAREPOINT\system»].UserToken;
    using (SPSite site = new SPSite(properties.SiteId, token))
    {
        using (SPWeb currentWeb = site.OpenWeb(properties.RelativeWebUrl))
        {
            try
            {
                DisableEventFiring();

                SPList sourceList = currentWeb.Lists[properties.ListId];
                SPListItem itemAdded = sourceList.GetItemById(properties.ListItem.ID);
                ……

            }
            catch (Exception ex1)
            {
                properties.ErrorMessage = ex1.Message;
                properties.Status = SPEventReceiverStatus.CancelWithError;
            }
            finally
            {
                EnableEventFiring();
            }

        }
    }
}

 

Fuera del contexto de Sharepoint

Para poder ejecutar el modelo de objetos de Sharepoint fuera del contexto de sharepoint, es decir en un proceso distinto, ya sea un servicio web en otro workerprocess o una aplicación de consola.

En este caso nuestro código se ejecutará con las credenciales del usuario que maneje el proceso.

Este caso lo utilizaremos cuando tengamos que hacer integraciones con sistemas que no pueden migrarse o aplicaciones para migrar contenido.

Para utilizar este método el usuario con el que hagamos logon además de tener acceso al site debe tener el privilegio “Actuar como parte del sistema operativo”, en mi caso le he dado permisos de administrador de la máquina directamente. Si no lo hacemos nos permitirá conectar pero nos dará una excepción al acceder a los elementos de las listas.

Podéis consultar más ejemplos: http://support.microsoft.com/kb/306158/es

En mi caso he creado una aplicación de consola que muestra el contenidos de una lista:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;
using Microsoft.SharePoint;

namespace ConsoleApplication1
{
    class Program
    {

        const int LOGON32_PROVIDER_DEFAULT = 0;
        const int LOGON32_LOGON_NETWORK = 3;

        [DllImport(«advapi32.dll», SetLastError = true)]
        private static extern bool LogonUser(String lpszUsername, String
        lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        [DllImport(«kernel32.dll», CharSet = CharSet.Auto)]
        private extern static bool CloseHandle(IntPtr handle);

        [DllImport(«advapi32.dll», CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int DuplicateToken(IntPtr hToken,
            int impersonationLevel,
            ref IntPtr hNewToken);

        [DllImport(«advapi32.dll», CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool RevertToSelf();

 

        static void Main(string[] args)
        {
            WindowsImpersonationContext context = impersonateValidUser(«miusuario», «midominio», «password»);
            try
            {
                using (SPSite site = new SPSite(«http://localhost/))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        Console.WriteLine(web.Lists[«milista»].Title);
                        foreach (SPListItem item in web.Lists[«milista»].Items)
                            Console.WriteLine(item.Title);
                    }
                }
            }
            finally
            {
                context.Undo();
            }

            Console.ReadLine();
        }

        private static WindowsImpersonationContext impersonateValidUser(String userName, String domain, String password)
        {
            WindowsIdentity tempWindowsIdentity;
            WindowsImpersonationContext impersonationContext;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (RevertToSelf())
            {
                if (LogonUser(userName, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref token))
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        impersonationContext = tempWindowsIdentity.Impersonate();
                        if (impersonationContext != null)
                        {
                            CloseHandle(token);
                            CloseHandle(tokenDuplicate);
                            return impersonationContext;;
                        }
                    }
                }
            }
            if (token != IntPtr.Zero)
                CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
            return null;
        }

    }
}

Publicado por

Mario Cortés

Mario Cortés Flores es MVP en Office 365, trabaja en Plain Concepts como Team Lead y escribe habitualmente en geeks.ms/blogs/mcortes y en Twitter @mariocortesf. Podréis encontrarlo colaborando activamente con la comunidad de MadPoint y SUGES

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *