Este artigo foi traduzido por máquina.

Segurança do SharePoint

Segurança personalizada e baseada em declarações no SharePoint 2010

Feng Marfim

Patrick Stanko
Shabbir Darugar

Baixar o código de exemplo

2010 Do Microsoft SharePoint introduziu um novo modelo de identidade baseada em declarações para criar aplicativos com reconhecimento de declarações. Quando um usuário trata de um aplicativo com reconhecimento de declarações, ela apresenta uma identidade para o aplicativo como um conjunto de declarações. Essas declarações permitem uma autorização mais granular ao conteúdo. Assim, os usuários com determinados atributos, como, por exemplo, o código de país e departamento, têm acesso ao conteúdo apropriado.

Implementando a segurança baseada em declarações em nível corporativo apresenta alguns desafios interessantes. Vamos explorar o processo de criação de um provedor de declarações personalizadas (CCP) no SharePoint, integrar isso Microsoft FAST Search Server 2010 para SharePoint, gerenciando conteúdo habilitado para declarações da perspectiva do usuário e evitando a certas armadilhas. Como podemos fazer isso, você aprenderá como projetar e implementar um modelo de segurança baseada em declarações de personalizado dinâmica em 2010 do SharePoint. Usaremos o portal de recursos humanos da empresa Contoso, ContentWeb, para o nosso exemplo.

Visão geral do aplicativo

A Contoso é uma empresa global com Fechar para 100 mil funcionários e ContentWeb armazena uma profusão de informações que os autores de conteúdo precisam gerenciar diária para semanalmente. Na maioria dos casos, o conteúdo é aplicável ao pessoal em um país, mas não um outro, para uma disciplina, mas não um outro, ou a todos os funcionários da Contoso. Parte do conteúdo, no entanto, é dados confidenciais que precisam estar disponível para apenas um pequeno subconjunto de funcionários (como vice-presidentes).

Para cobrir um público amplo, o ContentWeb usa grupos do SharePoint (SPGs) com declarações personalizadas para proteger e direcionar o conteúdo de explicitamente. Declarações específicas às necessidades da Contoso são armazenadas em um banco de dados e usadas para definir declaração "conjunto" um usuário. É este conjunto de declarações que determina o que um funcionário pode e não consigo ver. Uma interface administrativa permite que os operadores de informações que suportam a alteração de portal ou aumentar o seu próprio conjunto de declarações, dando-lhes a capacidade de exibir o portal como um usuário diferente. Esse poderoso recurso personalizado é chamado modo de exibição de Portal como (VPAS).

ContentWeb usa a autenticação do Windows baseada em declarações em 2010 do SharePoint e 2010 do servidor de pesquisa rápida para o SharePoint como o mecanismo de pesquisa em um ambiente de pesquisa federada enterprise.

Por que uma CCP?

Quando um usuário faz logon em ContentWeb, a autenticação do Windows baseada em declarações fornece um conjunto de declarações do Active Directory, que atua como o provedor de identidade. Entretanto, essas declarações sozinhas não são suficientes para ContentWeb proteger e direcionar o conteúdo. ContentWeb requer informações adicionais do usuário repositórios de dados corporativos, como SAP, para criar um conjunto de declarações completo que descreve o usuário. Portanto, precisamos de um CCP para aumentar as declarações. Usamos essas declarações personalizadas para explicitamente secure e direcionar o conteúdo para o usuário.

Ter um CCP permite a Contoso determinar quetipos de declaração e valores deseja usar para descrever a funcionários, fornecedores e outras pessoas, ele funciona com. Este modelo é dimensionável; Ele permite que a Contoso alterar com eficiência ao longo do tempo como suas mudanças nos negócios.

Porque você não pode editar facilmente as declarações provenientes do Active Directory, você também precisa de um CCP para oferecer suporte a VPAS. VPAS é usada principalmente quando quiser que uma pessoa autorizada (usuário) exibir o portal que outra pessoa (usuário B). Em tais casos, o provedor de declarações personalizadas adiciona as declarações personalizadas do usuário b em um conjunto de declarações do usuário A, assim, autorizando o usuário a exibir o conteúdo que o usuário b podem acessar.

As declarações de que um usuário possui são atributos que representam o seu "profile". Os usuários podem ter declarações simples e compostas. Declarações simples, como CountryCode e UserType, são fáceis de entender. ContentWeb usa um conjunto predefinido de declarações simples — ou, mais precisamente, os tipos de declaração simples. No entanto, às vezes, um funcionário precisa ter permissão para conteúdo que tenha mais de um tipo de declaração; Por exemplo, CountryCode = US E UserType = FullTimeEmployee — a condição AND. Nesse caso, você pode criar declarações de compostos.

Prontos para uso, o SharePoint 2010 avalia declarações no conjunto usando apenas a lógica OR de declarações de um usuário. Isso significa que o SharePoint 2010 oferece suporte somente a condição ou de segurança e direcionamento e nem sempre é suficiente. Vejamos um exemplo. ContentWeb tem uma declaração de CountryCode e uma declaração UserType. Ele precisa proteger alguns conteúdos para os EUA em tempo integral os funcionários usando CountryCode = US E UserType = FullTimeEmployee. Nós não pode satisfazer essa exigência diretamente em 2010 do SharePoint usando as declarações simples CountryCode ou UserType, portanto, precisamos criar uma declaração composta para representar a usar ambas as declarações.

Poderíamos criar um novo tipo de declaração para os EUA em tempo integral funcionários. No entanto, se a empresa cria novos escritórios em outros países, em seguida, precisamos atualizar nosso código de origem do CCP para adicionar tipos de declaração correspondente. Claramente, essa abordagem pode ser caro e demorado. Além disso, a equipe de negócios ContentWeb deseja ser capaz de adicionar e remover tipos de declaração composta sem a necessidade de uma nova versão do aplicativo cada vez. Como você pode ver, o ContentWeb requer um modelo de segurança dinâmica e extensível.

Como podemos gerenciará todos os dados de declarações? Vamos usar um banco de dados chamado ContentWebAdminDB para armazenar metadados de declaração. ContentWebAdminDB é declarações origem back-end; ele consolida todos os dados de origem de declarações da SAP e outros bancos de dados corporativos. Podemos falarei neste banco de dados mais daqui a pouco. E vamos usar um aplicativo ASP.NET aplicativo administrativo chamado ContentWebAdmin para se conectar a esse banco de dados para criar e atualizar os metadados de declarações compostos e configuração de VPAS. (Detalhes deste aplicativo são fora do escopo deste artigo). As declarações de compostos são criadas usando declarações simples. Por exemplo, no aplicativo ContentWebAdmin podemos criar uma declaração composta chamada US-FullTimeEmployee usando o CountryCode = US e UserType = FullTimeEmployee simples das solicitações. Com esses metadados de declaração de coumpound, para qualquer usuário que tenha CountryCode = US e UserType = reivindicações simples de FullTimeEmployee, uma nova declaração composta dos EUA-FullTimeEmployee = true será adicionado ao conjunto de declarações do usuário. Observe que nenhum composto reivindicar US-FullTimeEmployee = false aparece no conjunto de declarações de qualquer usuário. Com esse planejamento dinâmicas de declarações de compostos, cada usuário tem apenas algumas dúzia declarações no total, mesmo que a permutação de declarações compostas pode ser bastante alta. Esta é a chave para garantir o bom desempenho.

Quando um usuário entra no ContentWeb, o CCP é invocado. O CCP chama um procedimento armazenado personalizado, sp_GetUserClaims, no ContentWebAdminDB durante a passagem de declaração de identidade do usuário. O procedimento armazenado verifica a configuração de VPAS e retorna todas as declarações simples e compostas para o usuário para o CCP. Como você pode ver, dinâmicas de declarações compostas não são as mesmas regras de autorização dinâmico. Nossas solução não altera a maneira como o SharePoint 2010 de declarações compostas avalia as declarações. Nós simplesmente injetar declarações compostas conjuntos de declarações do usuário baseados na configuração de metadados de declarações de compostos. Figura 1 mostra uma visão geral do ContentWeb.

A High-Level View of ContentWeb
Figura 1 uma visão geral do ContentWeb

Dentro do provedor de declarações personalizadas de ContentWeb

O CCP ContentWeb tem uma classe especial que herda de Microsoft.SharePoint.Administration.SPClaimProvider. Figura 2 mostra parte dessa classe. Observe a linha 16 do código (onde a propriedade exibirtexto é definida). Adicionamos a ele para ajudar a tornar nosso personalizado declarações de tipos e valores de exibição de uma maneira mais amigável e legível.

Figura 2 reclamações mais legível

protected override void FillResolve(
  Uri context, string[] entityTypes, SPClaim resolveInput,
  List<Microsoft.SharePoint.WebControls.PickerEntity> resolved)
{
  string claimTypeName = string.Empty;
  string claimValue = string.Empty;
 
  // Handles only ContentWeb claim types
  if (null != resolveInput && resolveInput.ClaimType.Contains(
    ContentWebClaimTypes.ContentWebClaimTypePrefix))
  {
    claimValue = resolveInput.Value.ToLower();
    claimTypeName = GetName(resolveInput.ClaimType);
 
    PickerEntity entity = CreatePickerEntity();
    entity.Claim = resolveInput;
    entity.Description = resolveInput.ClaimType + " = " + claimValue;
    entity.DisplayText = claimTypeName + " = " + claimValue;
    entity.EntityData[PeopleEditorEntityDataKeys.DisplayName] =
      claimTypeName + " = " + claimValue;
    entity.EntityType = SPClaimEntityTypes.User;
    entity.IsResolved = true;
    resolved.Add(entity);
  }
}

O CCP ContentWeb precisa de uma seqüência de conexão para chamar um procedimento armazenado em ContentWebAdminDB para declarações de usuário. Como o CCP é um recurso de nível de farm, não é dentro do escopo de qualquer aplicativo da Web, portanto, não podemos usar o arquivo Web. config para configurar a seqüência de conexão de banco de dados. Poderíamos usar Machine. config, mas que não é ideal porque temos diversos front-ends da Web. Em vez disso, usaremos o armazenamento hierárquico do objeto do SharePoint, SPPersistedObject, armazenar a seqüência de conexão de banco de dados. Isso é armazenado do banco de dados de configuração do SharePoint, disponibilizando a seqüência de conexão de banco de dados para todos os front-ends da Web farm do SharePoint.

Dentro o CCP ContentWeb, podemos criar uma classe que herda de Microsoft.SharePoint.Administration.SPPersistedObject, conforme mostrado na a Figura 3.

Figura 3 A classe ConnectionStringStorage

[Guid("56705e15-abd3-44f0-adea-91488da1a572")]
public class ConnectionStringStorage
  : Microsoft.SharePoint.Administration.SPPersistedObject
{
    [Persisted]
    private string m_connectionString;
 
    public ConnectionStringStorage()
    {
    }
 
    public ConnectionStringStorage(
      string name, SPPersistedObject parent)
      : base(name, parent)
    {
    }
 
    public ConnectionStringStorage(
      string name, SPPersistedObject parent, Guid guid)
      : base(name, parent, guid)
    {
    }
 
    public string ConnectionString
    {
      get { return m_connectionString; }
      set { m_connectionString = value; }
    }
}

Usaremos o seguinte script de Windows PowerShell para registrar a seqüência de conexão de banco de dados:

[System.Reflection.Assembly]::LoadWithPartialName(
  "Microsoft.Sample.ContentWeb.ClaimsSecurity")
$id = new-object System.Guid("56705e15-abd3-44f0-adea-91488da1a572")
$farm = Get-SPFarm
$existingObject = $farm.GetObject($id)
$existingObject.Delete()
$newObject =
  new-object Microsoft.Sample.Contoso.ClaimsSecurity.ConnectionStringStorage(
  "ConnectionString", $farm, $id)
$newObject.ConnectionString = "Data Source=ContentWebAdminSQLServer;
  Initial Catalog=ContentWebAdminDB;Integrated Security=True;Timeout=30"
$newObject.Update();
Iisreset

Como você pode ver, é preciso fazer referência a dll do CCP. Criamos um novo objeto de ConnectionStringStorage e defina sua propriedade ConnectionString. Finalmente, chamamos o método de atualização para salvá-lo para o banco de dados de configuração do SharePoint.

Recomendamos que a seqüência de conexão tem um valor de tempo limite de menos de 60 segundos. O CCP tem um tempo limite padrão de execução de 60 segundos. Isso significa que, se a conexão de banco de dados expirar, você tem a capacidade de capturar a exceção real da seqüência de conexão em vez de um muito clara a partir da execução do CCP.

Dentro do construtor do CCP, nós irá recuperar a seqüência de conexão e armazená-lo em uma variável de nível de módulo:

public class ContentWebClaimProvider : SPClaimProvider
{
  private static string connectionString = null;
 
  public ContentWebClaimProvider(string displayName)
    : base(displayName)
  {
    Guid guid = new Guid(@"56705e15-abd3-44f0-adea-91488da1a572");
    ConnectionStringStorage storage =
      (ConnectionStringStorage)SPFarm.Local.GetObject(guid);
    connectionString = storage.ConnectionString;
  }
}

Queremos ser capaz de rastrear quando o CCP se conecta ao banco de dados para as declarações do usuário. 2010 SharePoint possui um novo recurso que é perfeito para isso. Ele chamou o objeto Microsoft.SharePoint.Utilities.SPMonitoredScope, e ele monitora o desempenho e uso de recursos para um bloco de código especificado. O código a seguir registra chamadas de banco de dados do CCP:

using (new SPMonitoredScope("ContentWeb.CCP.GetUserClaims", 5))
{
  userClaimsDataSet = CustomClaimSourceDA.GetUserClaims(
    userAlias, connectionString);
}

Também é possível configurar o nível de rastreamento deste evento e evento na Administração Central do SharePoint. Esses são controlados pelo objeto de monitoramento na categoria SharePoint Foundation em Monitoring | Emissão de relatórios | Configure o log de diagnóstico.

Dentro do banco de dados de ContentWebAdminDB

Como observado anteriormente, ContentWebAdminDB consolida dados do usuário do SAP e outros bancos de dados corporativos e contém a origem da declaração personalizada. O CCP ContentWeb chama um procedimento armazenado, sp_GetUserClaims, para recuperar as declarações personalizadas do usuário.

O aplicativo de ContentWebAdmin permite que usuários autorizados configurar avisos de sinistro compostos e VPAS para um usuário. ContentWebAdminDB armazena os metadados de configuração composta de declarações e a configuração de VPAS em tabelas. Quando o CCP ContentWeb chama sp_GetUserClaims, esse procedimento armazenado será VPAS configuração e, em seguida, retornar tanto declarações simples e compostos. O projeto detalhado e a implementação desse banco de dados está fora do escopo deste artigo. No entanto, incluímos um script SQL para um procedimento de sp_GetUserClaims fictício armazenados com valores de declaração embutidos dentro do pacote de código para download.

Uso de grupos do SharePoint

Um SPG é um wrapper lógico de usuários do SharePoint. Isso é útil para ContentWeb, que utiliza centenas de declarações de compostos. Sem SPGs, seria muito difícil para os autores de conteúdo gerenciar todas as declarações.

Usar o SPGs oferece os seguintes benefícios:

  • Atribuição de nome amigável: SPGs permitir aos usuários criar nomes de grupo amigável e significativo para a declaração potencialmente confusos para os valores. Por exemplo, ContentWeb tem um SPG denominado "Nos funcionários" que descreve os usuários que têm a declaração de valores país = dos Estados Unidos, CompanyCode = 1010 e UserSubType = FTE.
  • Suporte de resolução de nome de seletor pessoas: o controle de selecionador de pessoas em 2010 SharePoint naturalmente oferece suporte à resolução de nomes para SPGs. Isso torna mais fácil localizar e selecionar SPGs, conforme mostrado na a Figura 4.

SharePoint Groups in People Picker
Figura 4 grupos do SharePoint no seletor de pessoas

  • Gerenciamento de segurança de declaração dinâmico: suponha que você precisará alterar a definição de "Nos funcionários," Adicionando UserType = Corp, para os outros atributos — país = dos Estados Unidos, CompanyCode = 1010 e UserSubType = FTE — devido a mudanças nos precisa. É fácil fazer a alteração em apenas que um SPG e todos os objetos protegidos no que SPG automaticamente herdaria essa alteração.
  • **Apenas um SPG para protegendo e direcionamento de conteúdo:**2010 SharePoint agora oferece suporte a capacidade de proteger e um objeto usando o mesmo SPG de destino. Isso elimina a sobrecarga normal associada à criação de audiências, importação de perfis de usuário, executando o trabalho de sincronização de perfil e assim por diante para o direcionamento.
  • Várias declarações associados com um SPG: digamos que você precisa proteger uma página para funcionários em tempo integral, cujo nível varia de 60 a 65. Você pode facilmente fazer isso criando um SPG com declarações de compund para UserSubType = FTE e Level = 60, UserSubType = FTE e Level = 61… UserSubType = FTE e Level = 65. SharePoint 2010 interpreta todas essas declarações como "OR".

Gerenciar SPGs muitos tem o potencial de ser demorado, complicado e sujeito a erros. A equipe de negócios ContentWeb usa um arquivo do Excel para gerenciar centenas de grupos com declarações personalizadas associados.

Há várias opções para automatizar a criação de SPGs. Criamos um script de Windows PowerShell que lê dados de um arquivo XML para automatizar esse procedimento. (Você encontrará esse script no download de código, o que pode ser baixado em code.msdn.microsoft.com/mag201111SPSecurity.) Podemos preencher o arquivo de dados XML usando o arquivo do Excel da equipe de negócios. Figura 5 mostra o arquivo de configuração XML de exemplo.

Figura 5 arquivo de configuração do XML de exemplo

<?xml version="1.0" encoding="utf-8"?>
<SharePointGroups url="http://contentweb" owner="contoso\ivfeng" >
  <SharePointGroup name="ContentWeb-FTE"
    description="ContentWeb-FTE" permissionLevel="Read">
    <Claim type="UserType" value="emp"/>
  </SharePointGroup>
  <SharePointGroup name="ContentWeb_US_0000_Emp_Corp_HRPro"
    description="ContentWeb_US_0000_Emp_Corp_HRPro">
    <Claim type="CompoundClaim" value="US+emp+corp+hrpro"/>
  </SharePointGroup>
  <SharePointGroup name="ContentWeb_US_0000_Emp_Corp_Manager"
     description="ContentWeb_US_0000_Emp_Corp_Manager">
    <Claim type="CompoundClaim" value="us+emp+corp+manager"/>
    <Claim type="CompoundClaim" value="US+emp+corp+hrpro"/>
  </SharePointGroup>
</SharePointGroups>

Usando SPGs para destino

Para usar o direcionamento, você precisa que o aplicativo do serviço de perfil de usuário habilitado para o aplicativo Web.

Há um problema complicado serem observadas ao usar SPGs para direcionamento. Inicialmente, descobrimos que a SPGs que contém os usuários do Active Directory ou grupos de segurança foram bem trabalhando todas as, mas os SPGs que contém os usuários de declaração personalizada funcionou em todos os. A causa raiz foi relacionada ao nível de permissão desses grupos. Quando criamos as SPGs com declarações personalizadas, não queremos atribuir qualquer nível de permissão padrão. No entanto, se um SPG não é atribuída a um nível de permissão quando criado e usado posteriormente para segurança, ela será sinalizada com um nível de permissão especial chamado acesso limitado, como mostrado na a Figura 6.

A SharePoint Group with Limited Access
Figura 6 o grupo do SharePoint com acesso limitado

Como ContentWeb tem centenas de SPGs e a maioria deles é usada apenas para o público-alvo, eles não têm qualquer nível de permissão definido. No entanto, o processador de público-alvo de destino não pode extrair esses SPGs sem qualquer nível de permissão. Estamos tivesse sorte e descobriu uma solução alternativa via a permissão de interface do usuário da página que estamos foram aplicando para o público-alvo. Podemos concedido "Leitura" permissão para as SPGs que está sendo usado para o público-alvo e imediatamente desfez essa permissão. Esse processo faz com que o SharePoint sinalizar essas SPGs com o nível de permissão de acesso limitado, e o público-alvo homenageia Felizmente esse nível de permissão. É importante observar que você não precise passar por este Grant Number e desfazer o processo para os SPGs várias vezes. Você precisa fazê-lo apenas uma vez dentro da árvore de herança de segurança. Lembre-se de que, se você quebrar a herança de segurança, você precisará fazê-lo novamente, mesmo se você já fez isso no nível pai.

A implementação de pesquisa para ContentWeb

Um dos nossos objetivos principais com este aplicativo foi melhorar a experiência de pesquisa para os funcionários da Contoso. Nós queríamos ContentWeb para criar conteúdo muito mais detectáveis que ele tinha sido no passado.

Para fazer isso para ContentWeb, nós usamos 2010 do servidor de pesquisa rápida para o SharePoint hospedado em um ambiente federado. Voltar ao aFigura 1 para a Contoso do federado ambiente da pesquisa rápida. Isso mostra um farm do SharePoint denominado FAST Search Farm de Federação. Por trás deste farm é Microsoft FAST servidor de pesquisa para o banco de dados e o mecanismo do SharePoint. O farm de pesquisa rápida contém todos os o consulta pesquisa serviço aplicativos (consulta SSAs) e um conteúdo SSA.

Naturalmente, criamos uma fonte de conteúdo dentro do SSA conteúdo existente. (Servidor de pesquisa rápida recomenda o SSA conteúdo apenas uma). Depois que isso for feito, o SSA o conteúdo rastreado o banco de dados de conteúdo do ContentWeb e disponibilizar o índice de pesquisa para ContentWeb e outros aplicativos de intranet.

Em seguida, criou um SSA separado de consulta e publicá-lo para ContentWeb. Com o teste inicial de pesquisa em ContentWeb, descobrimos que trabalhou de pesquisa básica, mas o aparamento de segurança de pesquisa não estava funcionando conforme o esperado. Para as páginas protegidas com declarações personalizadas de ContentWeb, os usuários não conseguia visualizar os links nos resultados, mesmo que eles tinham as permissões de segurança. Podemos finalmente percebeu que precisávamos ter a ContentWeb os mapeamentos de tipo de declaração personalizada registrados do farm do SharePoint de pesquisa rápida para o aparamento de segurança de pesquisa trabalhar. A maneira mais simples de fazer isso é implantar o CCP no farm do SharePoint de pesquisa rápida. Não só tínhamos que confirmar o tipo de declaração mapeamentos foram registrados, também tínhamos certificar-se de que todas as identificações de declaração (mostrado como conta no a Figura 7) eram os mesmos entre todas as farms do SharePoint para o mesmo par de valor do tipo de declaração.

Claim IDs
Figura 7 IDs de declaração

No momento, mesmo com as atualizações cumulativas do SharePoint 2011 de junho de 2010, tipo mapeamentos de declarações em 2010 do SharePoint são imutáveis. Quando um CCP é implantado em um farm do SharePoint 2010, os mapeamentos de tipo de declaração são registrados e permanecem inalterados, mesmo se você remove e reimplanta o CCP. Como você pode ter CCPs em vários farms do SharePoint, é muito importante que você implanta todos os CCPs na mesma seqüência para garantir que a declaração de IDs são iguais entre todos os farms. Se você não fizer isso, a seqüência de IDs não estarão alinhada e busca não retornar resultados precisos.

Quando o conteúdo de ContentWeb é rastreado, o CCP não é invocado. Tudo que precisamos é que os mapeamentos de tipo de declaração registrados no farm de pesquisa rápida para que o mecanismo do rastreador pode decodificar as declarações personalizadas de ContentWeb. Em seguida, ele armazena as declarações personalizadas decodificadas para segurança no índice de pesquisa. Remover o CCP ContentWeb é opcional porque os mapeamentos de tipo de declaração permanecerá. Além disso, não precisamos o CCP ContentWeb para aumentar as declarações de usuário no farm FAST Search.

Resultados da pesquisa de aparamento de segurança: Portais de Intranet da Contoso

Para o conteúdo de ContentWeb para que possam ser pesquisados a partir de outros portais de intranet da Contoso, você precisa garantir o seguinte:

  • Todos os portais de intranet que precisam trazer à tona o conteúdo de ContentWeb devem ser desenvolvidos em 2010 do SharePoint e ser aplicativos da Web baseada em declarações que usam a autenticação do Windows.
  • Todos os portais de intranet devem consultar o mesmo índice de pesquisa rápida.
  • Todos os portais de intranet devem ter o ContentWeb CCP instalado neles. (Se houver mais de uma CCP, todos eles devem ser instalados na mesma seqüência para garantir que a declaração que IDs são alinhados.)

Se todas essas condições forem atendidas, o conteúdo de ContentWeb será pesquisável por todos os portais de intranet da Contoso.

Conclusão

SharePoint 2010 oferece forte integração com a segurança baseada em declarações. Grupos do SharePoint, declarações e um provedor de declarações personalizadas permitem que você autorize o conteúdo para a empresa, amplamente, assim como em um nível granular. Como você pode ver, você pode satisfazer a muitos cenários com relativa facilidade.

Esse design permite aos desenvolvedores criar ferramentas eficientes que permitem que os operadores de informações (como a equipe de suporte) para alterar suas declarações e visualizar um site como um usuário diferente e, em seguida, reverter.

Assim como acontece com a maioria das novas implementações de design, nossa experiência não foi fornecido sem "oportunidades para aprender", mas o produto final era vale a pena-lo. O código de exemplo que fornecemos deve ajudar você avance na direção certa e desativado para um ótimo início como implantar o portal empresarial de última geração!

Jinhui (Marfim) Feng é engenheiro de desenvolvimento de software sênior na Microsoft trabalhando em seus aplicativos internos de recursos humanos.

Shabbir Darugar é um líder sênior de software de engenheiro e projeto de desenvolvimento na Microsoft trabalhando em seus aplicativos internos derecursos humanos.

Patrick Stanko é gerente de programa do cliente potencial, na Microsoft trabalhando em seus aplicativos internos de recursos humanos.

Graças ao especialista técnico seguir pela revisão deste artigo: Wisnowski de Tom