Adicionando sabão: Nome de usuário do cabeçalho e senha com WSE 3.0
-
22-09-2019 - |
Pergunta
Eu criei com sucesso um cliente WS que funciona corretamente quando não está usando a autenticação.
No entanto, o servidor (WebSphere) agora exige a adição de um token de nome de usuário de segurança WS, e estou tendo dificuldade em fazer isso. A mensagem de sabão resultante deve se parecer com a seguinte:
<soapenv:Envelope
xmlns:ns="http://foo.bar/1.0"
xmlns:ns1="http://www.witsml.org/schemas/140"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-2" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>foo</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bar</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">foooooobar==</wsse:Nonce>
<wsu:Created>2010-01-25T13:09:24.860Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ns:fooBar>...</ns:fooBar>
</soapenv:Body>
Eu baixei e instalei o WSE 3.0 SDK da Microsoft e adicionei uma referência à DLL no meu projeto Visual Studio 2005.
Agora tenho acesso ao Microsoft.Web.Services3.* Namespaces, mas atualmente estou perplexo sobre como proceder.
O código do cliente foi gerado automaticamente por uma referência da Web, então eu só faço uma pequena quantidade de trabalho para enviar a mensagem ao servidor não autenticado:
WS.FooResultHttpService ws = new WS.FooResultHttpService();
ws.Url = "http://foo.bar.baz";
ws.SendSomething(message);
Acabei de começar a investigar usando Microsoft.Web.Services3.Security.Tokens.UsernameTokenManager
, mas até agora não consegui colocar nada em funcionamento.
Qualquer dica seria muito apreciada, pois não consigo encontrar boas receitas na rede.
Obrigado!
Solução 2
Infelizmente consegui funcionar antes de ler Ótima resposta de Wsanville.
Para ajudar os outros, estou postando todas as etapas que precisava fazer para fazer isso trabalhar com o Visual Studio 2005:
- Instalar WSE 3.0, escolher personalizadas e selecione tudo
- Ler Implementando a autenticação direta com o token de nome de usuário no WSE 3.0 para dicas
- Relanomizar o Visual Studio 2005, agora clique com o botão direito do mouse no seu projeto no Solution Explorer, e você deve ter um Configurações do WSE 3.0 Item de menu e use isso, se desejar.
- Atualize suas referências da Web, isso deve criar uma nova classe de proxy de serviço da web http, com um nome diferente, por exemplo
YourWsNameHttpServiceWse
. Isso é essencialmente o mesmo que correr WSEWSDL3.EXE - Use esta nova classe e você deve ter acesso a métodos e propriedades da WSE, como
SetClientCredential
.
Acabei fazendo quase tudo no código, em vez de confiar nos arquivos de configuração que são construídos com minha dll C#. O código acabou sendo assim:
FooBarHttpServiceWse wse = new FooBarHttpServiceWse();
wse.SetClientCredential(new UsernameToken(
"username",
"password",
PasswordOption.SendPlainText));
wse.SetPolicy(new FooBarPolicy());
wse.CallSomeServerFunction(yourRequest)
Eu criei minha própria política, que parecia assim:
using Microsoft.Web.Services3.Design;
// ...
public class FooBarPolicy : Policy
{
public FooBarPolicy()
{
this.Assertions.Add(new UsernameOverTransportAssertion());
}
}
Finalmente, o servidor WebSphere respondeu que Um cabeçalho necessário que representa uma mensagem que endereça a propriedade não está presente, e inspecionar a mensagem de saída (usando a bela ferramenta Violinista) Vi a falha de sabão do servidor indicava que o cabeçalho de ação estava faltando.
Eu tentei em vão definir o wsa:Action
elemento eu mesmo:
using Microsoft.Web.Services3.Addressing;
// ...
wse.RequestSoapContext.Addressing.Action = new Action("CallSomeServerFunction");
O problema era que, mesmo que eu estivesse uma ação, quando foi enviada sobre o fio, estava vazio. Acontece que eu tive que abrir a aula de proxy da WSE e editar um atributo lá:
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"---Edit this to set wsa:Action---",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
// ...
public SomeServerFunction(...)
Depois disso, tudo deu certo.
Outras dicas
Certifique -se de que sua classe de proxy herda Microsoft.Web.Services3.WebServicesClientProtocol
.
Você pode fazer isso alterando a classe proxy em si ou gerando -a através da linha de comando usando WSEWSDL3.EXE com o /type:webClient
trocar.
Você pode passar as credenciais como esta:
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Security.Tokens;
using Microsoft.Web.Services3.Security;
.
.
.
WS.FooResultHttpService ws = new WS.FooResultHttpService();
ws.RequestSoapContext.Security.Tokens.Add(new UsernameToken("blah", "blah", PasswordOption.SendPlainText));
Foi o que eu fiz no passado para obter o WSE3.0 no Studio 2008. Espero que ajude.