Pergunta

A minha pergunta é em relação ao melhor (aka "menos dolorosa") caminho para o acesso seguro para um serviço WCF que só é exposto a usuários internos da nossa empresa. O objetivo é garantir que o serviço só é acessado através de uma única aplicação Windows Forms que cada um de nossos usuários tem instalado. Quando o serviço é chamado, eu quero o serviço a ser capaz de validar que foi chamado a partir da aplicação permitida.

O serviço a ser protegido usos BasicHttpBinding, que suporta streaming, então eu acredito que estou limitado a segurança em nível de transporte.

versões Abaixo estão simplificadas das seções <bindings> e <services> de arquivo de configuração do meu serviço.

<bindings>
  <basicHttpBinding>
    <binding name="Service1Binding" transferMode="Streamed"/>    
  </basicHttpBinding>
</bindings>

<services>
    <service name="WCFServiceSecurity.Service1" 
        behaviorConfiguration="WCFServiceSecurity.Service1Behavior">
        <endpoint address=""
            binding="basicHttpBinding"
            contract="WCFServiceSecurity.IService1"
            bindingConfiguration="Service1Binding"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
</services>

Alguém pode oferecer alguns detalhes quanto ao que ações que eu precisaria para tomar a fim de implementar a segurança neste serviço?

Nota:. Eu sou novo para o WCF e não estou familiarizado com a segurança em tudo, então deixe-me saber se eu não forneceram detalhes suficientes


UPDATE:

Como sugerido por marc_s , Eu gostaria de proteger o serviço WCF usando algum tipo de mecanismo de nome de usuário / senha. Isto dá um pouco de direção mais para uma resposta, mas eu ainda estou um pouco desfocadas no como para realmente fazer isso.

Porque o meu serviço requer streaming para ser habilitado, eu tenho que usar a segurança em nível basicHttpBinding e Transportes (certo?); Para além disso, o método referido no meu serviço só pode aceitar um objeto Stream.

Tomar essas restrições em consideração juntamente com a minha preferência para usar nome de usuário / senha de validação ...

  • Como devo modificar o arquivo de configuração do meu serviço para forçar as credenciais de usuário / senha a ser fornecida?
  • Como o meu serviço de validar as credenciais fornecidas?
  • Como os meus aplicativo cliente credenciais passa o serviço ao fazer uma chamada?
  • Será que este exigir o uso de SSL e, se assim for, vai todas as máquinas clientes exigem um certificado bem?

UPDATE:

Depois de explicar o problema que eu tenho tido com a segurança este serviço para meu chefe, me foi dado o sinal verde para tentar a rota de autenticação do Windows. Infelizmente, eu não teve sorte na implementação deste tipo de autenticação com o meu serviço Streamed (argh). Depois de fazer as alterações apropriadas (conforme descrito aqui - o único ser excepção que o meu transferMode="Streamed") e acessar o meu serviço, eu foi apresentado com o seguinte erro:

solicitação HTTP streaming não pode ser usado em conjunto com a autenticação HTTP. Desabilite pedido de streaming ou especificar a autenticação HTTP anônima.

Então eu tropecei em cima da seguinte citação aqui que oferece alguns esclarecimentos:

Você não pode fazê-auth transporte. com fluência. Se você tem que usar HTTP pedido de streaming, você vai ter que correr sem segurança.

O modo de segurança funciona é:

WCF cliente faz uma solicitação HTTP para o servidor.

Os responde Server com algo dizendo: "Você não está autorizado, envia-me um básico / digest / etc credencial."

O cliente recebe essa resposta e reenvia a mensagem com as credenciais embutido.

Agora, o servidor recebe a mensagem, verifica as credenciais, e continua. Pedido ao vivo não está concebido para trabalhar com esse padrão de segurança. Se o fizesse, seria muito lento, uma vez que o cliente iria enviar todo o fluxo, obter a mensagem do servidor que não foi autorizado, em seguida, ele teria que reenviar todo o fluxo com credenciais.

Então agora eu estou procurando opiniões, como você garantir o seu serviço WCF streaming de habilitado? Como mencionado anteriormente, uma espécie de nome de usuário / senha mecanismo seria preferível. Sinta-se livre para pensar fora da caixa em um presente ...

Qualquer ajuda é muito apreciada!

Foi útil?

Solução

Bem, eu encontrei um monte de questões que envolvem a segurança / streaming ao trabalhar sobre este problema. O hack (er ... hum ... solução temporária) eu finalmente acabei indo com foi a de criar um novo DataContract que herda MemoryStream e decorado com uma propriedade BaseStream (para prender os dados que eu quero streaming), juntamente com propriedades adequadas utilizadas para autenticação simples.

Aqui está o DataContract resultante:

[DataContract]
[KnownType( typeof( MemoryStream ) )] 
public class StreamWithCredentials : MemoryStream
{
    [DataMember]
    public Stream BaseStream { get; set; }

    [DataMember]
    public string Username { get; set; }

    [DataMember]
    public string Password { get; set; }
}

O acima DataContract acaba sendo o parâmetro de entrada do método de meu serviço. A primeira ação meu serviço toma é para autenticar as credenciais fornecidas contra valores válidos conhecidos e continuar conforme o caso.

Agora eu faço sabe que este é não a opção mais segura, mas o meu directiva era evitar o uso de SSL ( que eu não estou mesmo certo é possível de qualquer maneira - como afirmou aqui ) para este processo interno.

Dito isto, esta foi a melhor solução para o problema indicado acima eu poderia vir acima com, espero que isso ajude alguém aflito com esta questão.

Obrigado a todos que responderam.

Outras dicas

Há uma série de coisas que você poderia fazer:

  • adicionar um certificado para cada máquina que está autorizado a usar o seu serviço, e verificar se há esse certificado. Que só permite a exclusão de máquinas "não autorizadas" - você não pode limitá-lo a uma aplicação específica
  • mesmo que acima, mas incluem o certificado incorporado em seu winforms aplicativo e enviá-lo de lá (não armazená-lo no armazenamento de certificados da máquina)
  • exigir um nome de usuário / senha que somente esse aplicativo específico de vocês conhece e pode transmitir ao seu serviço; por exemplo. outra pessoa não seria capaz de apresentar as credenciais adequadas

EDIT 2: OK, então a abordagem nome de usuário / senha parece sair da mão .... E se você só tem a segurança de transporte básico (SSL) para a proteção básica, e depois usar o MessageContract para definir cabeçalho e corpo de sua mensagem SOAP, incluem um valor específico no cabeçalho, e em seguida, basta verificar que a presença do elemento no cabeçalho no seu serviço?

Algo assim:

[DataContract]
class YourRequestData
{
 ...
}

[MessageContract]
public class YourRequest
{
  [MessageBodyMember]
  public YourRequestData bodyData { get; set; }

  [MessageHeader]
  public string AppThumbprint { get; set; }
}

E, em seguida, em seu servidor em seu código apenas verificar a presença e a validade desse código AppThumbprint:

public Stream RequestStream(YourRequest request)
{
  if(AppThumbprintIsValid(request.AppThumbprint))
  {
     .... begin your streaming
  }
}

Isso pode acabar sendo muito mais fácil do que o cenário de segurança nome de usuário / senha.

Marc

Por favor me corrija se eu estiver errado, mas:

Se você estiver usando autenticação de formulários para o seu serviço WCF (em asp.net), basta adicionar um método de login para o seu serviço, em que você cria o cookie necessário (formsAuthentication.Authenticate ()). que é automaticamente enviada com a resposta, o cliente pode então chamar o API fluxo sem precisar parâmetros extras (um requisito para que seja STREAM) e você pode verificar a identidade na API de streaming antes de disparar o fluxo de retorno.

Como para garantir o acesso a todo o WCF, fico com a sensação de que a incorporação de um certificado no aplicativo .net é um caminho a percorrer. eles teriam que ildump seu aplicativo para chegar a ele.

você pode dizer asp.net/wcf não fornecer o WSDL, ou mais precisamente, para não gerar automaticamente o WSDL. Sem acesso wsdl ele fica muito mais difícil para eles para gerar um proxy ....

Se você quiser usar basicHttpBinding (para interoperabilidade), você só pode passar a sua credencial no nível de mensagem. Você tem que definir sua configuração de segurança para TransportWithMessageCredential.

Para fazer isso você tem que criar um canal SSL, então você precisa de um certificado no lado do servidor, e não é necesary para a cliente para ter um.

É possível utilizar a autenticação do Windows com Streaming e SSL, mas você deve usar TransportWithMessageCredential:

<basicHttpBinding>
    <binding name="FileService.FileServiceBinding" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed">
        <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
        <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="Windows" />
        </security>
    </binding>
</basicHttpBinding>

Você precisa definir em proxy.ClientCredentials.UserName.UserName código e proxy.ClientCredentials.UserName.Password.

Se isso vai ser um aplicativo que vidas na intranet, pode ser mais fácil simplesmente criar um novo grupo no Active Directory e só dar membros desse grupo a capacidade de usar o serviço.

Você pode adicionar autenticação (usando credenciais do Windows) com algo como isto:

<basicHttpBinding> 
 <security mode="TransportCredentialOnly"> 
  <transport clientCredentialType="Windows" /> 
 </security> 
</basicHttpBinding> 

poderia, então, autorizar, através de decorar a interface para seus métodos de serviços:

<PrincipalPermission(SecurityAction.Demand, Role:="MyAppsUsers")> _ 
Public Function MyMethod() As String Implements IService.MyMethod 

Aqui está um bom link para Segurança no WCF. Tem muita Como de no final (aquele intitulado 'How To - Use basicHttpBinding com Autenticação e TransportCreditals do Windows' pode ser de utilidade para você).
Wcf Secruity

[Disclaimer: Eu também sou novo para o WCF e não ter feito neste caso exato antes, então desculpas se isso é um pouco fora]

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