Разрешение за предоставяне на нова колекция от сайтове чрез работен поток

Заседнал съм в много странна ситуация.

Имам работен процес, който използвам за осигуряване на нов сайт в моето уеб приложение. Този работен поток използва една дейност по персонализиран работен поток, за да осигури сайта с помощта на следния оператор.

---друг код е пропуснат за яснота----

SPSiteCollection.Add()

Това изявление хвърля следващо изключение, когато акаунтът ми за пул приложения не е същият като акаунта за пул приложения на Central Admin.

Достъпът е отказан. (Изключение от HRESULT: 0x80070005 (E_ACCESSDENIED)) в Microsoft.SharePoint.SPGlobal.HandleUnauthorizedAccessException(UnauthorizedAccessException ex) в Microsoft.SharePoint.Library.SPRequest.CreateSite(Guid gApplicationId, String bstrUrl, Int32 lZone, Guid gSiteId, Guid gDatabaseId, String bstrDat

след много гугъл и констатации аз нулирах до разрешението за акаунта на Applicaiton Pool.

Кодът на работния поток винаги се изпълнява под системния акаунт (идентификация на набора от приложения). За да създаде нова колекция от сайтове на SharePoint, наборът от приложения изисква достъп до базата данни "SharePoint_Config".

Когато моето уеб приложение работи под идентификационните данни на групата приложения на Central Admin, то има целия достъп до конфигурационната база данни. Но когато изпълнявам под каквато и да е друга идентичност на пула от приложения, която има по-малко разрешение. хвърля изключение, дори ако дам разрешение на DBO за акаунта на пула на приложенията в базата данни за конфигурация.

Моят регистър на събитията на приложението има следния запис: -

Източник на събитие: Windows SharePoint Services 3 Категория на събитието: База данни ИД на събитие: 3760 Дата: 2/3/2010 Час: 2:36:16 AM Потребител: N/A Компютър: SHAREPOINT20 Описание: SQL база данни „SharePoint_Config“ на екземпляр на SQL Server houspsr001' не е намерен. По-долу е включена допълнителна информация за грешка от SQL Server.

Не може да се отвори база данни „SharePoint_Config“, поискана от влизането. Входът е неуспешен. Неуспешно влизане за потребител „DOMAIN\WebAppPool“.

За повече информация вижте Центъра за помощ и поддръжка на http://go.microsoft.com/fwlink/events.asp.

Въпросът ми е... задължително ли е да стартирате такъв код под акаунта на пула на приложенията на централния администратор.

Някакво решение за това....?

Въпросът ми


person Sudhir Kesharwani    schedule 03.02.2010    source източник


Отговори (2)


Най-накрая проблемът с отказан достъп е решен. Както посочих в предишния си имейл, проблемът се дължи на недостатъчно разрешение за самоличността на групата ми приложения.

  • Централното администриране работеше под различна идентичност на група приложения
  • Уеб приложенията се изпълняват под различна идентичност на група приложения.

Моят работен поток използваше ElevatedPrevilages за предоставяне на колекция от сайтове и използваше за получаване на отказ за достъп от базата данни, тъй като нямаше разрешение за промяна на базата данни на SharePoint_Config.

Разрешение За да разреша този проблем, трябваше да се представя за самоличността на групата приложения на Central Admin. Ето необходимия метод за имитиране на потребител на набор от приложения на Central Admin.

   #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

И тогава моят код за създаване на колекция от сайтове изглежда така: -

//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();
person Sudhir Kesharwani    schedule 09.02.2010

Тъй като не ми е позволено да коментирам отговора на Sudhir, публикувам забележката си като отговор. Използвах основно същия код, който Sudhir предлага като решение. Имитирането работи, но има пропуск в сигурността. Ако съхраните паролата си като обикновен текстов (управляван) низ, тя може да бъде преместена в паметта и дори съхранена на твърдия диск поради страниране. Това улеснява неавторизирани лица да шпионират вашите идентификационни данни.

Поради това се препоръчва да използвате SecureString за тази цел. Как това може да се използва във връзка със SecureString може да се търси на MSDN. Основната разлика с решението на Sudhir е да се използва различно претоварване на LogonUser, а именно

[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);

и го използвайте по следния начин (този код е от 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);

По този начин паролата се криптира само точно преди да я използваме за влизане на потребителя. След това незабавно паролата в обикновен текст се освобождава от паметта.

person binford    schedule 20.12.2010
comment
Благодаря, че подобри този отговор, бинфорд, сигурен съм, че ще помогне на някой в ​​нужда :) - person Sudhir Kesharwani; 20.05.2013