Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este exemplo demonstra como implementar uma política de autorização de reivindicação personalizada e um gerenciador de autorização de serviço personalizado associado. Isso é útil quando o serviço faz verificações de acesso baseadas em declarações em operações de serviço e, antes das verificações de acesso, concede ao chamador determinados direitos. Este exemplo mostra o processo de adição de declarações, bem como o processo para fazer uma verificação de acesso em relação ao conjunto finalizado de declarações. Todas as mensagens de aplicativo entre o cliente e o servidor são assinadas e criptografadas. Por padrão, com a wsHttpBinding associação, um nome de usuário e uma senha fornecidos pelo cliente são usados para fazer logon em uma conta válida do Windows. Este exemplo demonstra como utilizar um personalizado UserNamePasswordValidator para autenticar o cliente. Além disso, este exemplo mostra o cliente autenticando-se no serviço usando um certificado X.509. Este exemplo mostra uma implementação de IAuthorizationPolicy e ServiceAuthorizationManager, que concedem acesso a métodos específicos do serviço para usuários específicos. Esta amostra é baseada no Nome do Usuário de Segurança de Mensagem, mas demonstra como executar uma transformação de declaração antes de ServiceAuthorizationManager ser chamado.
Observação
O procedimento de instalação e as instruções de build para este exemplo estão localizados no final deste tópico.
Em resumo, este exemplo demonstra como:
O cliente pode ser autenticado usando um nome de usuário e senha.
O cliente pode ser autenticado usando um certificado X.509.
O servidor valida as credenciais do cliente em relação a um validador personalizado
UsernamePassword.O servidor é autenticado usando o certificado X.509 do servidor.
O servidor pode usar ServiceAuthorizationManager para controlar o acesso a determinados métodos no serviço.
Como implementar IAuthorizationPolicy.
O serviço expõe dois pontos de extremidade para se comunicar com o serviço, definidos usando o arquivo de configuração App.config. Cada ponto de extremidade consiste em um endereço, uma associação e um contrato. Uma associação é configurada com uma associação padrão wsHttpBinding que usa WS-Security e autenticação de nome de usuário do cliente. A outra associação é configurada com uma associação padrão wsHttpBinding que usa WS-Security e autenticação de certificado do cliente. O <comportamento> especifica que as credenciais do usuário devem ser usadas para autenticação de serviço. O certificado do servidor deve conter o mesmo valor da SubjectName propriedade que o findValue atributo no <serviceCertificate>.
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<!-- configure base address provided by host -->
<add baseAddress ="http://localhost:8001/servicemodelsamples/service"/>
</baseAddresses>
</host>
<!-- use base address provided by host, provide two endpoints -->
<endpoint address="username"
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
<endpoint address="certificate"
binding="wsHttpBinding"
bindingConfiguration="Binding2"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<!-- Username binding -->
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
<!-- X509 certificate binding -->
<binding name="Binding2">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior" >
<serviceDebug includeExceptionDetailInFaults ="true" />
<serviceCredentials>
<!--
The serviceCredentials behavior allows one to specify a custom validator for username/password combinations.
-->
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.MyCustomUserNameValidator, service" />
<!--
The serviceCredentials behavior allows one to specify authentication constraints on client certificates.
-->
<clientCertificate>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it will be trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having to have certificates issued by a certification authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust" />
</clientCertificate>
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by a client to authenticate the service and provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
-->
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
<serviceAuthorization serviceAuthorizationManagerType="Microsoft.ServiceModel.Samples.MyServiceAuthorizationManager, service">
<!--
The serviceAuthorization behavior allows one to specify custom authorization policies.
-->
<authorizationPolicies>
<add policyType="Microsoft.ServiceModel.Samples.CustomAuthorizationPolicy.MyAuthorizationPolicy, PolicyLibrary" />
</authorizationPolicies>
</serviceAuthorization>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Cada configuração de ponto de extremidade do cliente consiste em um nome de configuração, um endereço absoluto do ponto de extremidade do serviço, a vinculação e o contrato. A associação de cliente é configurada com o modo de segurança apropriado, conforme especificado nesse caso na <segurança> e clientCredentialType conforme especificado na <mensagem>.
<system.serviceModel>
<client>
<!-- Username based endpoint -->
<endpoint name="Username"
address="http://localhost:8001/servicemodelsamples/service/username"
binding="wsHttpBinding"
bindingConfiguration="Binding1"
behaviorConfiguration="ClientCertificateBehavior"
contract="Microsoft.ServiceModel.Samples.ICalculator" >
</endpoint>
<!-- X509 certificate based endpoint -->
<endpoint name="Certificate"
address="http://localhost:8001/servicemodelsamples/service/certificate"
binding="wsHttpBinding"
bindingConfiguration="Binding2"
behaviorConfiguration="ClientCertificateBehavior"
contract="Microsoft.ServiceModel.Samples.ICalculator">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<!-- Username binding -->
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
<!-- X509 certificate binding -->
<binding name="Binding2">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<serviceCertificate>
<!--
Setting the certificateValidationMode to PeerOrChainTrust
means that if the certificate
is in the user's Trusted People store, then it will be
trusted without performing a
validation of the certificate's issuer chain. This setting
is used here for convenience so that the
sample can be run without having to have certificates
issued by a certification authority (CA).
This setting is less secure than the default, ChainTrust.
The security implications of this
setting should be carefully considered before using
PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode = "PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</behaviors>
</system.serviceModel>
Para o ponto de extremidade baseado em nome de usuário, a implementação do cliente define o nome de usuário e a senha a serem usados.
// Create a client with Username endpoint configuration
CalculatorClient client1 = new CalculatorClient("Username");
client1.ClientCredentials.UserName.UserName = "test1";
client1.ClientCredentials.UserName.Password = "1tset";
try
{
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = client1.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
...
}
catch (Exception e)
{
Console.WriteLine("Call failed : {0}", e.Message);
}
client1.Close();
Para o endpoint baseado em certificado, a implementação do cliente configura o certificado a ser utilizado.
// Create a client with Certificate endpoint configuration
CalculatorClient client2 = new CalculatorClient("Certificate");
client2.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "test1");
try
{
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = client2.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
...
}
catch (Exception e)
{
Console.WriteLine("Call failed : {0}", e.Message);
}
client2.Close();
Este exemplo usa um personalizado UserNamePasswordValidator para validar nomes de usuário e senhas. O exemplo implementa MyCustomUserNamePasswordValidator, derivado de UserNamePasswordValidator. Consulte a documentação sobre UserNamePasswordValidator para obter mais informações. Para fins de demonstrar a integração com o UserNamePasswordValidatorexemplo de validador personalizado, este exemplo de validador personalizado implementa o Validate método para aceitar pares de nome de usuário/senha em que o nome de usuário corresponde à senha, conforme mostrado no código a seguir.
public class MyCustomUserNamePasswordValidator : UserNamePasswordValidator
{
// This method validates users. It allows in two users,
// test1 and test2 with passwords 1tset and 2tset respectively.
// This code is for illustration purposes only and
// MUST NOT be used in a production environment because it
// is NOT secure.
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
{
throw new SecurityTokenException("Unknown Username or Password");
}
}
}
Depois que o validador for implementado no código de serviço, o host de serviço deverá ser informado sobre a instância do validador a ser usada. Isso é feito usando o seguinte código:
Servicehost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new MyCustomUserNamePasswordValidatorProvider();
Ou você pode fazer a mesma coisa na configuração:
<behavior>
<serviceCredentials>
<!--
The serviceCredentials behavior allows one to specify a custom validator for username/password combinations.
-->
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.MyCustomUserNameValidator, service" />
...
</serviceCredentials>
</behavior>
O WCF (Windows Communication Foundation) fornece um modelo avançado baseado em declarações para executar verificações de acesso. O ServiceAuthorizationManager objeto é usado para executar a verificação de acesso e determinar se as declarações associadas ao cliente atendem aos requisitos necessários para acessar o método de serviço.
Para fins de demonstração, este exemplo mostra uma implementação de ServiceAuthorizationManager que implementa o método CheckAccessCore para permitir o acesso de um usuário a métodos com base em declarações do tipo http://example.com/claims/allowedoperation, onde o valor é o URI da ação da operação que está autorizada a ser chamada.
public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
string action = operationContext.RequestContext.RequestMessage.Headers.Action;
Console.WriteLine("action: {0}", action);
foreach(ClaimSet cs in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
{
if ( cs.Issuer == ClaimSet.System )
{
foreach (Claim c in cs.FindClaims("http://example.com/claims/allowedoperation", Rights.PossessProperty))
{
Console.WriteLine("resource: {0}", c.Resource.ToString());
if (action == c.Resource.ToString())
return true;
}
}
}
return false;
}
}
Após a implementação do ServiceAuthorizationManager personalizado, é necessário informar ao host de serviço sobre qual ServiceAuthorizationManager utilizar. Isso é feito conforme mostrado no código a seguir.
<behavior>
...
<serviceAuthorization serviceAuthorizationManagerType="Microsoft.ServiceModel.Samples.MyServiceAuthorizationManager, service">
...
</serviceAuthorization>
</behavior>
O método principal IAuthorizationPolicy a ser implementado é o método Evaluate(EvaluationContext, Object).
public class MyAuthorizationPolicy : IAuthorizationPolicy
{
string id;
public MyAuthorizationPolicy()
{
id = Guid.NewGuid().ToString();
}
public bool Evaluate(EvaluationContext evaluationContext,
ref object state)
{
bool bRet = false;
CustomAuthState customstate = null;
if (state == null)
{
customstate = new CustomAuthState();
state = customstate;
}
else
customstate = (CustomAuthState)state;
Console.WriteLine("In Evaluate");
if (!customstate.ClaimsAdded)
{
IList<Claim> claims = new List<Claim>();
foreach (ClaimSet cs in evaluationContext.ClaimSets)
foreach (Claim c in cs.FindClaims(ClaimTypes.Name,
Rights.PossessProperty))
foreach (string s in
GetAllowedOpList(c.Resource.ToString()))
{
claims.Add(new
Claim("http://example.com/claims/allowedoperation",
s, Rights.PossessProperty));
Console.WriteLine("Claim added {0}", s);
}
evaluationContext.AddClaimSet(this,
new DefaultClaimSet(this.Issuer,claims));
customstate.ClaimsAdded = true;
bRet = true;
}
else
{
bRet = true;
}
return bRet;
}
...
}
O código anterior mostra como o Evaluate(EvaluationContext, Object) método verifica se nenhuma nova declaração foi adicionada que afeta o processamento e adiciona declarações específicas. As declarações permitidas são obtidas do GetAllowedOpList método, que é implementado para retornar uma lista específica de operações que o usuário tem permissão para executar. A política de autorização adiciona reivindicações para permitir o acesso à operação específica. Isso é usado posteriormente pelo ServiceAuthorizationManager para realizar decisões relacionadas à verificação de acesso.
Depois que a personalização IAuthorizationPolicy for implementada, o host de serviço precisa ser informado sobre as políticas de autorização a serem utilizadas.
<serviceAuthorization>
<authorizationPolicies>
<add policyType='Microsoft.ServiceModel.Samples.CustomAuthorizationPolicy.MyAuthorizationPolicy, PolicyLibrary' />
</authorizationPolicies>
</serviceAuthorization>
Quando você executa o exemplo, as solicitações e respostas da operação são exibidas na janela do console do cliente. O cliente chama com êxito os métodos Add, Subtract e Multiple e obtém uma mensagem "O acesso é negado" ao tentar chamar o método Divide. Pressione ENTER na janela do cliente para desligar o cliente.
Arquivo de configuração em lote
O arquivo Setup.bat em lote, incluído com esta amostra, permite que você configure o servidor com os certificados relevantes para executar um aplicativo auto-hospedado que exige segurança baseada em certificado do servidor.
O seguinte fornece uma breve visão geral das diferentes seções dos arquivos em lotes para que possam ser modificadas para serem executadas na configuração apropriada:
Criando o certificado do servidor.
As linhas a seguir do arquivo em lote Setup.bat criam o certificado do servidor a ser usado. A variável %SERVER_NAME% especifica o nome do servidor. Altere essa variável para especificar o nome do seu próprio servidor. O valor padrão é localhost.
echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -peInstalando o certificado do servidor no repositório de certificados confiável do cliente.
As linhas a seguir no arquivo em lote Setup.bat copiam o certificado do servidor no repositório de pessoas confiáveis do cliente. Essa etapa é necessária porque os certificados gerados pelo Makecert.exe não são implicitamente confiáveis pelo sistema cliente. Se você já tiver um certificado com raiz em um certificado raiz confiável do cliente, por exemplo, um certificado emitido pela Microsoft, essa etapa de preencher o repositório de certificados do cliente com o certificado do servidor não será necessária.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeopleCriando o certificado do cliente.
As linhas a seguir do arquivo em lote Setup.bat criam o certificado do cliente a ser usado. A variável %USER_NAME% especifica o nome do servidor. Esse valor é definido como "test1" porque esse é o nome que a
IAuthorizationPolicyprocura. Se você alterar o valor de %USER_NAME% deverá alterar o valor correspondente noIAuthorizationPolicy.Evaluatemétodo.O certificado é armazenado no repositório Meu (Pessoal) no local do repositório CurrentUser.
echo ************ echo making client cert echo ************ makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -peInstalando o certificado do cliente no repositório de certificados confiável do servidor.
As linhas a seguir no arquivo em lote Setup.bat copiam o certificado do servidor no repositório de pessoas confiáveis do cliente. Essa etapa é necessária porque os certificados gerados pelo Makecert.exe não são implicitamente confiáveis pelo sistema de servidores. Se você já tiver um certificado com raiz em um certificado raiz confiável, por exemplo, um certificado emitido pela Microsoft, essa etapa de preencher o repositório de certificados do servidor com o certificado do cliente não será necessária.
certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople
Para configurar e compilar o exemplo
Para criar a solução, siga as instruções na criação dos exemplos do Windows Communication Foundation.
Para executar a amostra em uma configuração de computador único ou entre computadores, use as instruções a seguir.
Observação
Se você usar Svcutil.exe para regenerar a configuração deste exemplo, modifique o nome do ponto de extremidade na configuração do cliente para corresponder ao código do cliente.
Para executar o exemplo no mesmo computador
Abra o Prompt de Comando do Desenvolvedor para Visual Studio com privilégios de administrador e execute Setup.bat na pasta de instalação da amostra. Isso instala todos os certificados necessários para executar o exemplo.
Observação
O arquivo em lote Setup.bat foi projetado para ser executado no Prompt de Comando do Desenvolvedor para Visual Studio. A variável de ambiente PATH definida no Prompt de Comando do Desenvolvedor para Visual Studio aponta para o diretório que contém executáveis exigidos pelo script Setup.bat .
Inicie Service.exe do service\bin.
Inicie Client.exe de \client\bin. A atividade do cliente é exibida no aplicativo de console do cliente.
Se o cliente e o serviço não puderem se comunicar, confira Dicas de solução de problemas para exemplos de WCF.
Para executar o exemplo em vários computadores
Crie um diretório no computador de serviço.
Copie os arquivos do programa de serviço de \service\bin para o diretório no computador de serviço. Copie também os arquivos Setup.bat, Cleanup.bat, GetComputerName.vbs e ImportClientCert.bat para o computador de serviço.
Crie um diretório no computador cliente para os binários cliente.
Copie os arquivos do programa cliente para o diretório do cliente no computador cliente. Copie também os arquivos Setup.bat, Cleanup.bate ImportServiceCert.bat para o cliente.
No servidor, execute
setup.bat serviceem um Prompt de Comando do Desenvolvedor para Visual Studio aberto com privilégios de administrador.A execução
setup.batcom oserviceargumento cria um certificado de serviço com o nome de domínio totalmente qualificado do computador e exporta o certificado de serviço para um arquivo chamado Service.cer.Edite Service.exe.config para refletir o novo nome do certificado (no
findValueatributo no <serviceCertificate>), que é o mesmo que o nome de domínio totalmente qualificado do computador. Altere também o nome do computador no <elemento service>/<baseAddresses> de localhost para o nome totalmente qualificado do seu computador de serviço.Copie o arquivo Service.cer do diretório de serviço para o diretório do cliente no computador cliente.
No cliente, execute
setup.bat clientem um Prompt de Comando do Desenvolvedor para Visual Studio aberto com privilégios de administrador.A execução
setup.batcom oclientargumento cria um certificado de cliente chamado test1 e exporta o certificado do cliente para um arquivo chamado Client.cer.No arquivo Client.exe.config do computador cliente, altere o valor do endereço do ponto de extremidade para que corresponda ao novo endereço do seu serviço. Faça isso substituindo localhost pelo nome de domínio totalmente qualificado do servidor.
Copie o arquivo Client.cer do diretório do cliente para o diretório de serviço no servidor.
No cliente, execute ImportServiceCert.bat em um Prompt de Comando do Desenvolvedor para Visual Studio aberto com privilégios de administrador.
Isso importa o certificado de serviço do arquivo Service.cer para o repositório CurrentUser – TrustedPeople .
No servidor, execute ImportClientCert.bat no Prompt de Comando do Desenvolvedor para Visual Studio aberto com privilégios de administrador.
Isso importa o certificado do cliente do arquivo Client.cer para o repositório LocalMachine – TrustedPeople .
No computador do servidor, inicialize Service.exe na janela do prompt de comando.
No computador cliente, inicialize Client.exe a partir de uma janela do prompt de comando.
Se o cliente e o serviço não puderem se comunicar, confira Dicas de solução de problemas para exemplos de WCF.
Limpar após a amostra
Para limpar após o exemplo, execute Cleanup.bat na pasta de exemplos quando terminar de executar o exemplo. Isso remove os certificados do servidor e do cliente do repositório de certificados.
Observação
Esse script não remove certificados de serviço em um cliente ao executar este exemplo em computadores. Se você tiver executado exemplos do WCF que usam certificados em computadores, certifique-se de limpar os certificados de serviço que foram instalados no repositório CurrentUser – TrustedPeople. Para fazer isso, use o seguinte comando: certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name> Por exemplo: certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com.