Pergunta

Encontrei a Solução

A solução foi adicionar um conjunto de Sites Raiz (como o código foi executado em um sub-site, sem que um site de raiz).

Ver Esta Solução


Atualização Importante (com base no feedback recebido até o momento)

Eu não tiver o Visual Studio instalado no Servidor SharePoint 2013.Todo o código é compilado em Visual Studio 2012 remotamente com o uso de referências necessárias para que o SharePoint 2013 DLLs e assinado digitalmente por isso ele pode ser implantado na Cache de Assemblagem Global no SharePoint Server 2013.

No nível mais básico esta declaração de falha no ponto de Page_Load();

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

Porque SPContext.Current é sempre null.

Fundo

Cliente necessidades de site do SharePoint para ser acessado usando Autenticação Baseada em Formulário para usuários externos e a Autenticação do Windows para usuários internos (empresa).Passaram e ter o programa de configuração, tanto os Provedores de Autenticação e agora obter o login padrão.

Sign In

Apesar de tudo funciona a Autenticação do Windows ainda exibe a seleção de Provedor de tela quando o cliente deseja a Autenticação do Windows para apenas passar automaticamente através de e exibir uma Autenticação Baseada em Formulários tela de login se que falha.

Foi lutando com isso por dias depois de olhar vários blogs e artigos que eu sinto que eu não sou mais adiante, e que é deprimente.No momento eu não posso treino se eu estou faltando alguma coisa realmente fundamental.

Página De Entrada Personalizada

A página é baseado fora de um ajuntamento de;

  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

Esta é apenas uma primeira tentativa e perceber que não precisa de todos esses controles, eventualmente, só queria ver como as coisas se relacionam.

MyCustomSignInModule Assembleia

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;
        }
    }
}

O Processo

Eu tenho um teste instância do Sharepoint em execução na máquina virtual, mas não o Visual Studio instalado como todo o desenvolvimento é feito remotamente.O atual processo de eu seguir;

  1. Construir Biblioteca de classes C# (este será MyCustomSignInModule.Dll)
  2. Assinar MyCustomSignInModule.Dll assim, ele pode ser colocado na VM GAC.
  3. Registar MyCustomSignInModule.Dll no GAC na VM instância.
  4. Salvar SignInForm.aspx no %CommonProgramFiles%\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ o que é equivalente a <SharePointSiteRoot>/_layouts/ diretório virtual no IIS.
  5. No site Administração Central do SharePoint definir a Página De entrada Personalizada para a minha página ~/_layouts/SignInForm.aspx.
  6. Redefinir o IIS usando iisreset.
  7. Teste acessando o site do SharePoint (este é o lugar onde ele cai).

O Problema

Sign In Error

Se não é claro que o erro é;

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.A corrente é nula por quê?

O NullReferenceException está a ser causado por SPContext.Current sendo nulo, mas eu não treino por que é nulo e nenhuma quantidade de artigos que eu olhei até agora não resultou em me ajudar a resolver isso.Eu estou esperando pelo lançamento de todo o meu processo aqui alguém pode ser capaz de apontar para mim que estou em falta ou fazendo de errado.

Foi útil?

Solução

Finalmente cheguei ao fundo do que estava causando o problema, em primeiro lugar gostaria de agradecer a ambos @MdMazzotti e @Hugo Madeira por sua persistente de ajuda.

No final, eu tropecei em uma solução que acabou por ser, em parte, porque a maneira como o site foi construído.No meu caso particular, o site foi construído como um sub-site do SharePoint, por qualquer motivo, isso significava que não havia nenhum conjunto de Sites na raiz do web site do SharePoint que foi a causa da Null SPContext no meu código.

Depois de adicionar um conjunto de Sites Raiz do meu código começou a funcionar como esperado.

Outras dicas

Eu só estou supondo aqui, mas aqui estão algumas coisas que eu acho que poderia ajudar.

Adicionar este código JavaScript para a página de entrada personalizada (antes da declaração if):

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

Você pode também adicionar esse JavaScript para a sua página para testar se ele funciona ou não, usando o console:

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

Se ela retorna algo, então temos de progresso!Se não, então eu vou ter de continuar a minha pesquisa, desde que eu encontrar a sua pergunta interessante.

EDITAR

Em vez de usar este código no lado do servidor:

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

Tente usar esta vez:

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

Eu procurei em volta e notou que em alguns dos exemplos de código que eu encontrei, o _iisSettings foi diferente da sua.Talvez seja por isso que o seu SPContext.A corrente é nula?

Por favor, verifique esta resposta:https://stackoverflow.com/questions/5081251/how-can-this-throw-a-nullreferenceexception

SPContext.Atual não funciona com Privilégios Elevados, então você tem que reescrever como na resposta acima.

Você pode verificar este artigo do MSDN: http://msdn.microsoft.com/en-us/library/office/ms468609(v=office.14).aspx

Eu acho que porque você usa uma Biblioteca de classes C# projeto no Visual studio, você não está em um contexto web e não pode usar SPContext.Atual, como explicado no artigo do MSDN acima.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a sharepoint.stackexchange
scroll top