2010-06-23 7 views
13

Java 기반 Axis2 웹 서비스에 연결하는 WCF 클라이언트가 있습니다. WS-Security가 적용될 예정이며 .NET 클라이언트를 수정해야합니다. 그러나 올바른 인증을 제공하기 위해 애 쓰고 있습니다. WSE 3.0이 더 쉽게 사용할 수 있다는 것을 알고 있지만 쓸모없는 기술로 돌아 가지 않기를 바랍니다.WS-Security와 함께 Axis 2 웹 서비스를 사용하는 WCF 클라이언트에서 오류가 발생합니다. UsernameToken PasswordDigest 인증 체계

비슷한 문제 (미해결)는 this, thisthis입니다.

같이해야하는 SOAP 메시지 : 그러나

<wsse:UsernameToken> 
    <wsse:Username><!-- Removed--></wsse:Username> 
    <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"><!-- Removed--></wsse:Password> 
    <wsse:Nonce><!-- Removed--></wsse:Nonce> 
    <wssu:Created>2010-05-28T12:50:33.675+01:00</wssu:Created> 
</wsse:UsernameToken> 

는 광산은 다음과 같습니다

<s:Header> 
<h:Security xmlns:h="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"></h:Security> 
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
<u:Timestamp u:Id="_0"> 
<u:Created>2010-06-23T10:31:23.441Z</u:Created> 
<u:Expires>2010-06-23T10:36:23.441Z</u:Expires> 
</u:Timestamp> 
<o:UsernameToken u:Id="uuid-d329b3b2-6a1f-4882-aea6-ec6b8a492de7-1"> 
<o:Username> 
<!-- Removed--> 
</o:Username> 
<o:Password> 
<!-- Removed--> 
</o:Password> 
</o:UsernameToken> 
</o:Security> 
</s:Header> 

내 클라이언트는 다음과 같습니다 P.S.를 SecurityHeaderType param이 필요합니다. 그게 뭐야? 다음과 같이

public MyAck SendRequest(MyRequest request) 
{ 
RemoteServicePortTypeClient client = new RemoteServicePortTypeClient(); 

client.ClientCredentials.UserName.UserName = "JAY"; 
client.ClientCredentials.UserName.Password = "AND"; 

    // what is the difference between the two different Credential types?? 
    //client.ClientCredentials.HttpDigest.ClientCredential.UserName = "SILENT"; 
    //client.ClientCredentials.HttpDigest.ClientCredential.Password = "BOB"; 

SecurityHeaderType sht = new SecurityHeaderType(); 
//sht.Any = ???; // How do I use this??? 
//sht.AnyAttr = ???; // How do I use this ??? 

// SecurityHeaderType is a required parameter 
return client.RemoteServiceOperation_Provider(sht, request); 
} 

는 현재 바인딩은 다음과 같습니다

<basicHttpBinding> 
    <binding name="CustomBinding"> 
     <security mode="TransportWithMessageCredential"> 
      <transport clientCredentialType="None"></transport> 
      <message clientCredentialType="UserName" /> 
     </security> 
    </binding> 
</basicHttpBinding> 

나는 또한 사용자 지정 바인딩을 시도하고 비슷한 오류가있어 :

<customBinding> 
    <binding name="myCustomBindingConfig"> 
    <security authenticationMode="UserNameOverTransport" 
     messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11" 
     securityHeaderLayout="Strict" 
     includeTimestamp="false"></security> 
    <textMessageEncoding messageVersion="Soap11"></textMessageEncoding> 
    <httpsTransport /> 
    </binding> 
</customBinding> 

그리고 엔드 포인트 (주소는 분명히 변화를 ...) :

<endpoint address="https://www.somecompany.com/uat/axis/services/RemoteServiceOperation_Provider" 
     binding="basicHttpBinding" bindingConfiguration="CustomBinding" 
     contract="RemoteService.RemoteServicePortType" 
     name="RemoteService_UAT" /> 

나는 사용자 정의 헤더, 토큰, 바인딩에 대한 많이 읽은

<ErrorID>0</ErrorID> 
<ErrorType>UNEXPECTED</ErrorType> 
<ErrorDescription><![CDATA[Array index out of range: 0]]></ErrorDescription> 
<TimeStamp>2010-06-23T13:28:54Z</TimeStamp> 

내 뇌가 완전히 혼란 다음과 같이 반환되는 ustom 잘못이다. 누구든지 올바른 형식으로 메시지를 보내는 단계별 프로세스를 제안 할 수 있습니까?

This은 사용자 지정 토큰을 사용하여 WCF를 처리하는 것처럼 보이지만 필요한 경우 다이제스트 및 nonce를 어떻게 적용해야합니까?

어떤 도움을 환영합니다.

업데이트

일부 제한적으로 성공했습니다. 필자는 Microsoft.Web.Services3 라이브러리를 사용하여 올바른 다이제스트로 UsernameToken을 만들었습니다.그때 나는 내 자신의 사용자 정의 동작을 만든 및 BeforeSendRequest 방법 나는 헤더 삽입하려면 다음을 수행했습니다 내가 그렇게 같은 동작을 추가

object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) 
{ 
    UsernameToken ut = new UsernameToken("USERNAME", "PASSWORD", PasswordOption.SendHashed); 

    XmlElement securityElement = ut.GetXml(new XmlDocument()); 

    MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityElement, false); 
    request.Headers.Add(myHeader); 

    return Convert.DBNull; 
} 

을 :

CustomBehavior behavior = new CustomBehavior("USERNAME", "PASSWORD"); 
client.Endpoint.Behaviors.Add(behavior); 

지금 볼 수 있습니다 헤더는 가로 질러가는 :

<s:Header> 
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
<wsse:UsernameToken wsu:Id="SecurityToken-c6aeb72d-4d36-4650-abd3-33cc66caac6d" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> 
<wsse:Username> 
<!-- Removed--> 
</wsse:Username> 
<wsse:Password> 
<!-- Removed--> 
</wsse:Password> 
<wsse:Nonce> 
<!-- Removed--> 
</wsse:Nonce> 
<wsu:Created>2010-06-24T16:23:58Z</wsu:Created> 
</wsse:UsernameToken> 
</Security> 
</s:Header> 

하지만 오류 받고 있어요 :

<soapenv:Fault> 
<faultcode xmlns="">soapenv:Server</faultcode> 
<faultstring xmlns="">WSDoAllReceiver: security processing failed; nested exception is: 
    org.apache.ws.security.WSSecurityException: General security error (WSSecurityEngine: Callback supplied no password for: USERNAME)</faultstring> 
<faultactor xmlns="">urn:Remote_Provider</faultactor> 
<detail xmlns=""> 
<CUSTOMError xmlns="urn:customerror:v01"> 
<ErrorID>0</ErrorID> 
<ErrorType>UNEXPECTED</ErrorType> 
<ErrorDescription><![CDATA[WSDoAllReceiver: security processing failed; nested exception is: 
    org.apache.ws.security.WSSecurityException: General security error (WSSecurityEngine: Callback supplied no password for: USERNAME)]]></ErrorDescription> 
<TimeStamp>2010-06-24T17:23:59Z</TimeStamp> 
</CUSTOMError> 
</detail> 
</soapenv:Fault> 
를 보안이 추적 및 로깅 설정은 속성과 그 노드의 내용을 제거 담요 경우

Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest" 

는 그러나, 나는 확실하지 않다 :

암호 노드에서 누락 된 유형 속성이있을 나타납니다. 진단 로깅에서 logKnownPii 설정을 사용하려고 시도했지만 보안 정보가 여전히 불분명합니다. 저것에 대한 아이디어가 있습니까?

답변

5

내 질문에서 UPDATE가 실제로 작동하는지 확인할 수 있습니다

object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) 
{ 
    UsernameToken ut = new UsernameToken("USERNAME", "PASSWORD", PasswordOption.SendHashed); 

    XmlElement securityElement = ut.GetXml(new XmlDocument()); 

    MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityElement, false); 
    request.Headers.Add(myHeader); 

    return Convert.DBNull; 
} 

그리고 클라이언트 :

CustomBehavior behavior = new CustomBehavior("USERNAME", "PASSWORD"); 
client.Endpoint.Behaviors.Add(behavior); 

오류 메시지는 무관했다. 보안 헤더는 매우 간단한은 BasicHttpBinding와 함께 작동 : 행동이의

<basicHttpBinding> 
    <binding name="BasicSOAPBinding"> 
     <security mode="Transport" /> 
    </binding> 
</basicHttpBinding> 

코드 샘플은 내 블로그에서 확인하실 수 있습니다 : http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/

+0

불행하게도,이 미래에 사라질 수 있습니다 뭔가 것 같습니다. ONVIF 사양은 "이 표준에서 정의 된 서비스는 [WS-UsernameToken]을 지원하는 레거시 장치를 제외하고는 에 따라 [RFC 2617]에 따라 다이제스트 인증을 사용하여 보호되어야합니다. 출처 : https://www.onvif.org/specs/core/ONVIF-Core-Specification-v1706.pdf 5.12.1 – cube45

1

나는 비슷한 문제가 최근에 있었고 WSE 이외의 솔루션을 찾는 것을 포기했습니다. 며칠 후 WSE 3.0 SDK 다운로드를 끝내고 WseWsdl3.exe를 사용하여 프록시 클래스를 생성하고 UsernameToken에 대한 새 정책을 만들었습니다. 나는 15 분 안에 뛰었습니다. 다음은 현재 나를 위해 일하고있다.

RemoteService service = new RemoteService(); //generated class 

UsernameToken token = new UsernameToken(username, password, PasswordOption.SendPlainText); 
Policy policy = new Policy(); 
policy.Assertions.Add(new UsernameOverTransportAssertion()); 

service.SetClientCredential(token); 
service.SetPolicy(policy); 

var result = service.MethodCall(); 
2

이 질문에 잘 기록 - 많은 감사합니다. @ Junto의 "어떻게 사용합니까?"주석을 참조하면 서비스 메소드의 SecurityHeader 매개 변수를 사용하여 헤더를 추가 할 수 있습니다. 아래 예를 포함 시켰습니다. 무슨 일이 일어나고 있는지 WS * DTD를 읽으려고 할 때 SvcUtil.exe 도구가 barfing이라고 생각합니다. "서비스 참조 추가"마법사를 사용할 때는 명확하지 않습니다. 그러나 명령 행에서 svcutil.exe를 실행할 때 매우 분명합니다. svcutil.exe가 WS * DTD를 읽지 못하기 때문에 SecurityHeader 객체가 제대로 개발되지 않았습니다. 그러나 Microsoft는. Any 속성을 제공합니다. .Any 속성으로 UsernameToken 클래스를 바로 serialize 할 수 있으며 헤더가 메시지에 추가됩니다. 다시 한번이 훌륭한 질문에 감사드립니다.

필요한 도구 :

Fiddler2 (or similar) -- you really can't figure any of this out without inspecting the http headers.

필수 참조 :

Microsoft.Web.Services3.dll -- you can reference this 2.0 framework assembly from your 4.0 assembly 

WCF 서비스 호출

은 어떻게 UsernameToken이 보안 헤더를 추가 할 SecurityHeader 매개 변수를 사용합니다 :

// Initialization of the service... 
_service = new MyService("MyEndpoint", RemoteUri); 

// etc.  

// Calling the service -- note call to GetSecurityHeader() 
_service.ServiceAction(GetSecurityHeader(), "myParam1"); 

// etc. 

/// <summary> 
/// Construct the WSE 3.0 Security Header 
/// </summary> 
private SecurityHeader GetSecurityHeader() 
{ 
    SecurityHeader h = new SecurityHeader(); 
    UsernameToken t = new UsernameToken(RemoteLogin, RemotePassword, PasswordOption.SendPlainText); 
    h.Any = new XmlElement[1]; 
    h.Any[0] = t.GetXml(new XmlDocument()); 
    return h; 
} 

의 App.config는 :

<system.serviceModel> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="MyBinding" closeTimeout="00:01:00" openTimeout="00:01:00" 
      receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" 
      bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
      maxBufferSize="1048576" maxBufferPoolSize="524288" maxReceivedMessageSize="1048576" 
      messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" 
      useDefaultWebProxy="true"> 
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
       maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
      <security mode="Transport"> 
      <transport clientCredentialType="None" proxyCredentialType="None" 
       realm="" /> 
      <message clientCredentialType="UserName" algorithmSuite="Default" /> 
      </security> 
     </binding> 
     </basicHttpBinding> 
    </bindings> 
    <client> 
     <endpoint address="http://myservice.com/service.asmx" 
      binding="basicHttpBinding" bindingConfiguration="MyBinding"    contract="MyContract" 
      name="MyEndpoint" /> 
    </client> 
    </system.serviceModel> 
+0

GetSecurityHeader()는 저에게 감사했습니다! – Robotron

관련 문제