Permiso para aprovisionar una nueva colección de sitios a través del flujo de trabajo

StackOverflow https://stackoverflow.com/questions/2190785

  •  25-09-2019
  •  | 
  •  

Pregunta

Estoy atrapado en una situación muy extraña.

Tengo un flujo de trabajo que utilizo para aprovisionar un sitio nuevo en mi aplicación web.Este flujo de trabajo utiliza una actividad de flujo de trabajo personalizada para aprovisionar el sitio mediante la siguiente declaración.

---otro código omitido para mayor claridad----

SPSiteCollection.Agregar()

Esta declaración genera la siguiente excepción cuando mi cuenta del grupo de aplicaciones no es la misma que la cuenta del grupo de aplicaciones del Administrador central.

Acceso denegado.(Excepción de HRESULT:0x80070005 (E_ACCESSDENIED)) en Microsoft.SharePoint.SPGlobal.HandleUnauthorizedAccessException(UnauthorizedAccessException ej) en Microsoft.SharePoint.Library.SPRequest.CreateSite(Guid gApplicationId, String bstrUrl, Int32 lZone, Guid gSiteId, Guid gDatabaseId, String bstrDat

Después de muchas búsquedas en Google y hallazgos, me puse a cero en el permiso de la cuenta del grupo de aplicaciones.

El código de flujo de trabajo siempre se ejecuta en la cuenta del sistema (la identidad del grupo de aplicaciones).Para crear una nueva colección de sitios de SharePoint, el grupo de aplicaciones requiere acceso a la base de datos "SharePoint_Config".

Cuando mi aplicación web se ejecuta con la credencial del grupo de aplicaciones de Administrador central, tiene todo el acceso a la base de datos de configuración.Pero cuando ejecuto bajo cualquier otra identidad de grupo de aplicaciones que tenga menos permiso.arroja una excepción, incluso si le doy permiso a DBO a la cuenta del grupo de aplicaciones en la base de datos de configuración.

El registro de eventos de mi aplicación tiene la siguiente entrada: -

Fuente del evento:Windows SharePoint Servicios 3 Categoría de Evento:Base de datos ID de evento:3760 Fecha:2/3/2010 Hora:2:36:16 Usuario:N/A Ordenador:SHAREPOINT20 Descripción:Base de datos SQL 'SharePoint_Config' en La instancia de SQL Server 'houspsr001' no fundar.Información de error adicional de SQL Server se incluye a continuación.

No se puede abrir la base de datos "SharePoint_Config" solicitado por el Iniciar sesión.El inicio de sesión falló.Error de inicio de sesión para el usuario 'DOMAIN\WebAppPool'.

Para obtener más información, consulte el centro de ayuda y soporte en http://go.microsoft.com/fwlink/events.asp.

Mi pregunta es... ¿es obligatorio ejecutar dicho código en la cuenta del grupo de aplicaciones del administrador central?

¿Alguna solución para esto...?

Mi pregunta

¿Fue útil?

Solución

Finalmente se resolvió el problema del acceso denegado.Como indiqué en mi correo electrónico anterior, el problema se debió a un permiso insuficiente para la identidad de mi grupo de aplicaciones.

  • El administrador central se estaba ejecutando con una identidad de grupo de aplicaciones diferente
  • Las aplicaciones web se ejecutan con una identidad de grupo de aplicaciones diferente.

Mi flujo de trabajo usaba ElevatedPrevilages para aprovisionar una colección de sitios y solía obtener acceso denegado de la base de datos porque no tenía permiso para modificar la base de datos SharePoint_Config.

Resolución Para resolver este problema, tuve que suplantar la identidad del grupo de aplicaciones de Central Admin.Este es el método requerido para hacerse pasar por el usuario del grupo de aplicaciones de Administración central.

   #region Application Pool Identity Impersonate

        protected static WindowsIdentity CreateIdentity(string User, string Domain, string Password)
        {
            // The Windows NT user token.
            IntPtr tokenHandle = new IntPtr(0);

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

            tokenHandle = IntPtr.Zero;

            // Call LogonUser to obtain a handle to an access token.
            int returnValue = LogonUser(User, Domain, Password,LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,out tokenHandle);

            //Check if the logon user method succeeded
            if (returnValue <= 0)
            {
                int ret = Marshal.GetLastWin32Error();
                throw new Exception("LogonUser failed with error code: " + ret);
            }

            //System.Diagnostics.Debug.WriteLine("Created user token: " + tokenHandle);

            //The WindowsIdentity class makes a new copy of the token.
            //It also handles calling CloseHandle for the copy.
            WindowsIdentity id = new WindowsIdentity(tokenHandle);
            CloseHandle(tokenHandle);
            return id;
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern int LogonUser(
            string lpszUsername,
            string lpszDomain,
            string lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            out IntPtr phToken
            );
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern int ImpersonateLoggedOnUser(
            IntPtr hToken
        );

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern int RevertToSelf();

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern int CloseHandle(IntPtr hObject);

        #endregion

Y luego mi código para crear una colección de sitios se ve así: -

//Impersonate the logged in user, ApplicationUser, LoginDomain and Password are exposed as property of the class.

WindowsImpersonationContext wiContext = CreateIdentity(this.ApplicationPoolUser, this.LoginDomain, this.SystemPassword).Impersonate();



//Provision new site collection and update the property for new site collection url.

using (SPSite newSiteCollection = spSiteColl.Add(SUGGESTEDURL, TITLE, DESC, LCID, WEBTEMPLATE, PRIMARYOWNER.LoginName, PRIMARYOWNER.Name, PRIMARYOWNER.Email, SECONDARYOWNER.LoginName, SECONDARYOWNER.Name, SECONDARYOWNER.Email))

{

this.SUGGESTEDURL = newSiteCollection.Url;

}



//Reset the impersonation.

wiContext.Undo();

Otros consejos

Como no puedo comentar sobre la respuesta de Sudhir, publico mi comentario como respuesta.Utilicé básicamente el mismo código que Sudhir propone como solución.La suplantación funciona, pero tiene un fallo de seguridad.Si almacena su contraseña como una cadena de texto sin formato (administrada), es posible que se mueva dentro de la memoria e incluso se almacene en el disco duro debido a la paginación.Esto facilita que personas no autorizadas espíen sus credenciales.

Por lo tanto, se recomienda utilizar SecureString para este fin.Puede consultar cómo se puede utilizar esto junto con SecureString MSDN.La principal diferencia con la solución de Sudhir es utilizar una sobrecarga diferente de LogonUser, a saber

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String username, String domain, 
                                      IntPtr password, int logonType, 
                                      int logonProvider, ref IntPtr token);

y utilícelo así (este código es de MSDN):

// Marshal the SecureString to unmanaged memory.
passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(pwdSecureString);

// Call LogonUser, passing the unmanaged (and decrypted) copy of
// the SecureString password.
returnValue = LogonUser(userName, domainName, passwordPtr,
                        LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, 
                        ref tokenHandle);

// Zero-out and free the unmanaged string reference.
Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr);

De esta manera, la contraseña solo se cifra justo antes de que la usemos para iniciar sesión como usuario.A continuación, la contraseña en texto plano se libera inmediatamente de la memoria.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top