Пользовательская страница входа в систему имеет значение SPContext.Current, которое всегда равно null

sharepoint.stackexchange https://sharepoint.stackexchange.com//questions/95952

Вопрос

Найдено решение

Решение состояло в добавлении корневого семейства сайтов (поскольку код выполнялся на подсайте, без корневого сайта).

Видеть Это решение


Важное обновление (основываясь на отзывах, полученных к настоящему времени)

У меня не установлена Visual Studio на сервере SharePoint 2013.Весь код компилируется в Visual Studio 2012 удаленно с использованием ссылок на необходимые библиотеки DLL SharePoint 2013 и имеет цифровую подпись, чтобы его можно было развернуть в глобальном кэше сборок на сервере SharePoint 2013.

На самом базовом уровне это утверждение терпит неудачу в точке Page_Load();

SPContext.Current.Site.WebApplication.GetIisSettingsWithFallback(
  SPContext.Current.Site.Zone
);

Потому что SPContext.Current является всегда null.

Фон

Клиенту необходимо, чтобы сайт SharePoint был доступен с использованием проверки подлинности на основе форм для внешних пользователей и проверки подлинности Windows для внутренних пользователей (корпоративных).Прошли и настроили обоих поставщиков аутентификации и теперь получаете вход по умолчанию.

Sign In

Хотя все работает, проверка подлинности Windows по-прежнему отображает экран выбора поставщика, когда клиент хочет, чтобы проверка подлинности Windows просто автоматически проходила, и отображает экран входа в систему с проверкой подлинности на основе форм, если это не удается.

Я боролся с этим в течение нескольких дней, после просмотра различных блогов и статей я чувствую, что не продвинулся дальше, и это удручает.На данный момент я не могу понять, не упускаю ли я чего-то действительно фундаментального.

Пользовательская страница входа в систему

Страница основана на объединении следующих;

  1. %CommonProgramFiles%\Microsoft Shared\Web Server Extensions\15\Template\IdentityModel\Login\default.aspx
  2. %CommonProgramFiles%\Microsoft Shared\Web Server Extensions\15\Template\IdentityModel\Forms\default.aspx

Это всего лишь первая попытка, и я понимаю, что в конечном итоге мне не понадобятся все эти элементы управления, просто хотел посмотреть, как все устроено.

Сборка модуля mycustomsignin

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using Microsoft.IdentityModel.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.IdentityModel;
using Microsoft.SharePoint.IdentityModel.Pages;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Claims;
using Microsoft.SharePoint.ApplicationRuntime;
using Microsoft.SharePoint.Diagnostics;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using System.IdentityModel.Tokens;
using System.Web.Configuration;

namespace MyCustomSignInModule
{
    public class SignInForm : FormsSignInPage
    {
        protected Label DebugText;

        private static SPIisSettings _iisSettings;

        internal static SPIisSettings iisSettings
        {
            get
            {
                if (_iisSettings == null)
                {
                    SPSecurity.RunWithElevatedPrivileges(delegate()
                    {
                        _iisSettings = SPContext.Current.Site.WebApplication.GetIisSettingsWithFallback(SPContext.Current.Site.Zone);
                    });
                }
                return _iisSettings;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            HttpRequest request = HttpContext.Current.Request;

            bool isWindowsAuth = false;
            string username = request["username"];
            string password = request["password"];


            // If no username is provided, it'll probably be Windows Authentication (NTLMv2 protocol)
            if (String.IsNullOrEmpty(username))
            {
                isWindowsAuth = true;
            }

            try
            {

                //SPIisSettings iisSettings = SPContext.Current.Site.WebApplication.IisSettings[SPUrlZone.Default];

                if (isWindowsAuth)
                {
                    // Windows Authentication it is

                    if (iisSettings.UseWindowsClaimsAuthenticationProvider)
                    {
                        SPAuthenticationProvider provider = iisSettings.WindowsClaimsAuthenticationProvider;
                        RedirectToLoginPage(provider); // This should cause automatic sign in
                    }
                }
                else
                {
                    // FBA authentication it is.

                    SPFormsAuthenticationProvider formsClaimsAuthenticationProvider = iisSettings.FormsClaimsAuthenticationProvider;

                    SecurityToken token = SPSecurityContext.SecurityTokenForFormsAuthentication(new Uri(SPContext.Current.Web.Url), formsClaimsAuthenticationProvider.MembershipProvider, formsClaimsAuthenticationProvider.RoleProvider, username, password, SPFormsAuthenticationOption.PersistentSignInRequest);

                    if (null != token)
                    {
                        EstablishSessionWithToken(token);
                        base.RedirectToSuccessUrl();
                    }
                }
            }
            catch (Exception ex)
            {
                DebugText.Text = ex.ToString();
            }

        }

        // Microsoft.SharePoint.IdentityModel.LogonSelector
        private void RedirectToLoginPage(SPAuthenticationProvider provider)
        {
            string components = HttpContext.Current.Request.Url.GetComponents(UriComponents.Query, UriFormat.SafeUnescaped);
            string url = provider.AuthenticationRedirectionUrl.ToString();
            if (provider is SPWindowsAuthenticationProvider)
            {
                components = EnsureUrlSkipsFormsAuthModuleRedirection(components, true);
            }
            SPUtility.Redirect(url, SPRedirectFlags.Default, this.Context, components);
        }

        // Microsoft.SharePoint.Utilities.SPUtility
        private string EnsureUrlSkipsFormsAuthModuleRedirection
            (string url, bool urlIsQueryStringOnly)
        {
            if (!url.Contains("ReturnUrl="))
            {
                if (urlIsQueryStringOnly)
                {
                    url = url + (string.IsNullOrEmpty(url) ? "" : "&");
                }
                else
                {
                    url = url + ((url.IndexOf('?') == -1) ? "?" : "&");
                }
                url = url + "ReturnUrl=";
            }
            return url;
        }

        // Microsoft.SharePoint.IdentityModel.Pages.IdentityModelSignInPageBase
        private void EstablishSessionWithToken(SecurityToken securityToken)
        {
            if (securityToken == null)
            {
                throw new ArgumentNullException("securityToken");
            }
            SPFederationAuthenticationModule fam = SPFederationAuthenticationModule.Current;
            if (fam == null)
            {
                throw new InvalidOperationException();
            }

            fam.SetPrincipalAndWriteSessionToken(securityToken);
        }

        private SPAuthenticationProvider
                GetAuthenticationProvider(string providerName)
        {
            SPIisSettings iisSettings =
                SPContext.Current.Site.WebApplication.IisSettings[SPUrlZone.Default];

            foreach (SPAuthenticationProvider currentProvider in
                        iisSettings.ClaimsAuthenticationProviders)
            {
                if (currentProvider.DisplayName.ToLower() ==
                            providerName.ToLower())
                {
                    return currentProvider;
                }
            }

            return null;
        }
    }
}

Процесс

У меня есть тестовый экземпляр Sharepoint, запущенный на виртуальной машине, но Visual Studio не установлена, поскольку вся разработка выполняется удаленно.Текущий процесс, которому я следую;

  1. Создайте библиотеку классов C# (это будет MyCustomSignInModule.Dll)
  2. Знак MyCustomSignInModule.Dll таким образом, он может быть помещен в GAC виртуальной машины.
  3. Зарегистрировать MyCustomSignInModule.Dll в GAC на экземпляре виртуальной машины.
  4. Сохранить SignInForm.aspx в тот %CommonProgramFiles%\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ что является эквивалентом <SharePointSiteRoot>/_layouts/ виртуальный каталог в IIS.
  5. На сайте Центра администрирования SharePoint установите для страницы пользовательского входа значение моя страница ~/_layouts/SignInForm.aspx.
  6. Сбросьте IIS с помощью iisreset.
  7. Протестируйте доступ к сайту SharePoint (на этом все заканчивается).

Проблема

Sign In Error

Если это не так ясно, то ошибка заключается в следующем;

System.NullReferenceException: Object reference not set to an instance of an object. at
MyCustomSignInModule.SignInForm.b__0() at 
Microsoft.SharePoint.SPSecurity.<>c__DisplayClass5.b__3() at
Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode) at 
Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param) at 
Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode) at MyCustomSignInModule.SignInForm.get_iisSettings() at 
MyCustomSignInModule.SignInForm.Page_Load(Object sender, EventArgs e) 

SPContext.Current равен null почему?

То NullReferenceException вызывается SPContext.Current значение null, но я не могу понять, почему оно равно null, и никакое количество статей, которые я просмотрел, до сих пор не помогло мне решить эту проблему.Я надеюсь, что, опубликовав весь мой процесс здесь, кто-нибудь сможет указать мне на то, что я упускаю или делаю неправильно.

Это было полезно?

Решение

Наконец-то разобрались с причиной проблемы, во-первых, хотели бы поблагодарить обоих @MdMazzotti и @Хью Вуд за их постоянную помощь.

В конце концов я наткнулся на исправление, которое, как оказалось, отчасти связано с тем, как был построен сайт.В моем конкретном случае сайт был создан как подсайт в SharePoint, по какой-то причине это означало, что в корне веб-сайта SharePoint не было семейства сайтов, что стало причиной Null SPContext в моем коде.

После добавления корневого семейства сайтов мой код начал работать так, как ожидалось.

Другие советы

Я просто предполагаю здесь, но вот некоторые вещи, которые, я думаю, могли бы помочь.

Добавьте этот JavaScript-код на страницу пользовательского входа (перед вашим if-оператором):

SP.SOD.executeFunc('SP.js', 'SP.ClientContext');

Вы также можете добавить этот JavaScript на свою страницу, чтобы проверить, работает он или нет, используя консоль:

var clientContext = new  SP.ClientContext.get_current(); 
console.log(clientContext);

Если это что-то возвращает, значит, у нас есть прогресс!Если нет, то мне придется продолжить свои поиски, поскольку я нахожу ваш вопрос интересным.

РЕДАКТИРОВАТЬ

Вместо использования этого серверного кода:

if (_iisSettings == null)
{
   SPSecurity.RunWithElevatedPrivileges(delegate()
   {
      _iisSettings = SPContext.Current.Site.WebApplication.GetIisSettingsWithFallback(SPContext.Current.Site.Zone);
   });
}
return _iisSettings;

Попробуйте использовать это вместо этого:

if (_iisSettings == null)
{
   SPSecurity.RunWithElevatedPrivileges(delegate()
   {
      _iisSettings = Microsoft.SharePoint.SPContext.Current.Site.WebApplication.GetIisSettingsWithFallback(Microsoft.SharePoint.SPContext.Current.Site.Zone);
   });
}
return _iisSettings;

Я поискал вокруг и заметил, что в некоторых примерах кода, с которыми я столкнулся, _iisSettings отличался от вашего.Возможно, именно поэтому ваш SPContext.Current равен null?

Пожалуйста, проверьте этот ответ:https://stackoverflow.com/questions/5081251/how-can-this-throw-a-nullreferenceexception

SPContext.Current не работает с повышенными привилегиями, поэтому вам придется переписать, как в ответе выше.

Можете ли вы проверить эту статью на MSDN: http://msdn.microsoft.com/en-us/library/office/ms468609 (v=office.14).aspx

Я думаю, поскольку вы используете проект библиотеки классов C# в Visual Studio, вы не находитесь в веб-контексте и не можете использовать SPContext.Current, как описано в статье MSDN выше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с sharepoint.stackexchange
scroll top