2014-01-27 5 views
4

WSDL을 통해 웹 서비스에 대한 연결을 만들려고합니다. 서비스의 인증이 인증서 교환으로 인증 된 TLS로 설명되었다고 들었습니다. 나는 Visual Studio의 "Add Service Reference"를 통해 클라이언트를 생성했습니다. 명령을 보낼 때 와이어 상어에서 "핸드 셰이크"를 볼 것으로 예상되지만 "클라이언트 안녕"초기화가 전송되는 것을 볼 수 없습니다.() (이 실행 시작) http://en.wikipedia.org/wiki/Transport_Layer_Security#Description상호 인증 (양방향 클라이언트 인증서 인증)을 사용하는 서비스 클라이언트

내 클라이언트가 C#에서 writen 여기

내가 연결을 테스트하기 위해 실행하고 전체 프로그램은 다음과 같습니다 :

서비스의 인증은 여기에 설명되어 있습니다

<system.diagnostics> 
    <sources> 
    <source name="System.Net"> 
     <listeners> 
     <add name="System.Net"/> 
     </listeners> 
    </source> 
    <source name="System.Net.Sockets"> 
     <listeners> 
     <add name="System.Net"/> 
     </listeners> 
    </source> 
    <source name="System.Net.Cache"> 
     <listeners> 
     <add name="System.Net"/> 
     </listeners> 
    </source> 
    </sources> 
    <switches> 
    <add name="System.Net" value="Verbose"/> 
    <add name="System.Net.Sockets" value="Verbose"/> 
    <add name="System.Net.Cache" value="Verbose"/> 
    </switches> 
    <sharedListeners> 
    <add name="System.Net" 
     type="System.Diagnostics.TextWriterTraceListener" 
     traceOutputOptions="None" 
     initializeData="network.log" 
    /> 
    </sharedListeners> 
    <trace autoflush="true"/> 
</system.diagnostics> 
:
public class ClientExample 
{ 
    private const string Url = 
     "https://xxxxxxxxx"; 

    public static void Run() 
    { 
     ServicePointManager.ServerCertificateValidationCallback += ValidateCertificate; 
     ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 

     PerformTest("Clear Cache", GetBinding()); 
    } 

    private static Binding GetBinding() 
    { 
     var bec = new BindingElementCollection 
      { 
       new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8), 
       new HttpsTransportBindingElement{ RequireClientCertificate = true } 
      }; 
     return new CustomBinding(bec); 
    } 

    private static void PerformTest(string test, Binding binding) 
    { 
     try 
     { 
      Console.ResetColor(); 
      Console.ForegroundColor = ConsoleColor.Green; 
      Console.WriteLine(test); 
      Console.ResetColor(); 

      var client = GetClient(binding); 
      SendMessage(client); 
     } 
     catch (Exception e) 
     { 
      DisplayError(e); 
     } 
    } 

    private static MyClient GetClient(Binding binding) 
    { 
     var endpointAddress = new EndpointAddress(Url); 

     var client = new MyClient(binding, endpointAddress); 

     if (client.ClientCredentials != null) 
     { 
      client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, 
                     X509FindType.FindBySubjectName, 
                     "xxxxxxxxxxxxx");     
     } 
     return client; 
    } 

    private static void SendMessage(ChargePointServiceClient client) 
    { 
     var response = client.clearCache("xxxxxxxxxxxxx", new ClearCacheRequest()); 
     Console.WriteLine(ClearCacheDescription(response)); 
    } 

    private static string ClearCacheDescription(ClearCacheStatus response) 
    { 
     switch (response) 
     { 
      case ClearCacheStatus.Accepted: 
       return "Accepted"; 
      case ClearCacheStatus.Rejected: 
       return "Rejected"; 
     } 

     return "Unkown"; 
    } 

    private static bool ValidateCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors) 
    { 
     switch (sslpolicyerrors) 
     { 
      case SslPolicyErrors.None: 
       return true; 
      case SslPolicyErrors.RemoteCertificateChainErrors: 
       DisplayWarningMessage("RemoteCertificateChainErrors"); 
       return false; 
      case SslPolicyErrors.RemoteCertificateNameMismatch: 
       DisplayWarningMessage("RemoteCertificateNameMismatch"); 
       return false; 
      case SslPolicyErrors.RemoteCertificateNotAvailable: 
       DisplayWarningMessage("RemoteCertificateNotAvailable"); 
       return false; 
      default: 
       DisplayWarningMessage("Unkown Certificate Validation Error"); 
       return false; 
     } 
    } 

    private static void DisplayError(Exception exception) 
    { 
     if (exception == null) 
      return; 

     Console.BackgroundColor = ConsoleColor.DarkRed; 
     Console.ForegroundColor = ConsoleColor.White; 
     Console.WriteLine(@"Exception"); 
     Console.ResetColor(); 
     Console.WriteLine(exception.Message); 

     if (exception.InnerException != null) 
      Console.WriteLine(); 

     DisplayError(exception.InnerException); 
    } 

    private static void DisplayWarningMessage(string message) 
    { 
     Console.BackgroundColor = ConsoleColor.DarkYellow; 
     Console.ForegroundColor = ConsoleColor.White; 
     Console.WriteLine(message); 
     Console.ResetColor(); 
    } 
} 

나는 나의의 app.config에 system.diagnostic를 통해 모든 네트워크 트래픽을 기록 6,

여기에 관심의 로그 라인의 일부는 다음과 같습니다

이것은 TLS 스트림이 생성되는 것을 확인 :

System.Net Information: 0 : [9040] TlsStream#50727427::.ctor(host=xxxxx, #certs=1) 

안전한 채널이 생성됩니다

System.Net Information: 0 : [9040] SecureChannel#11159819::.ctor(hostname=xxxxxxx, #clientCertificates=1, encryptionPolicy=RequireEncryption) 
System.Net Information: 0 : [9040] Enumerating security packages: 
System.Net Information: 0 : [9040]  Negotiate 
System.Net Information: 0 : [9040]  NegoExtender 
System.Net Information: 0 : [9040]  Kerberos 
System.Net Information: 0 : [9040]  NTLM 
System.Net Information: 0 : [9040]  TSSSP 
System.Net Information: 0 : [9040]  pku2u 
System.Net Information: 0 : [9040]  Schannel 
System.Net Information: 0 : [9040]  Microsoft Unified Security Protocol Provider 
System.Net Information: 0 : [9040]  LiveSSP 
System.Net Information: 0 : [9040]  WDigest 
System.Net Information: 0 : [9040]  CREDSSP 
System.Net Information: 0 : [9040] SecureChannel#11159819 - Attempting to restart the session using the user-provided certificate: [Version] 

확실하지 개인 키를 조회하는 이유 :

System.Net Information: 0 : [9040] SecureChannel#11159819 - Left with 1 client certificates to choose from. 
System.Net Information: 0 : [9040] SecureChannel#11159819 - Trying to find a matching certificate in the certificate store. 
System.Net Information: 0 : [9040] SecureChannel#11159819 - Locating the private key for the certificate: [Version] 

로그의이 시점에서 인증서가 교환 된 것으로 확인됩니다. 불행하게도 와이어 상어

지금 내 프로그램이 서비스 인증서를 확인하고 난 후 일부 암호화 된 데이터 교환 및 내 캐시 삭제 명령이

를 전송 볼

System.Net Information: 0 : [9040] SecureChannel#11159819 - Remote certificate was verified as valid by the user. 
System.Net Information: 0 : [9040] ProcessAuthentication(Protocol=Ssl3, Cipher=Rc4 128 bit strength, Hash=Sha1 160 bit strength, Key Exchange=RsaKeyX 2048 bit strength). 

처리를 시작합니다 ...이 확인되지 않습니다 서비스에서 암호화 된 응답을 받지만 메시지는 오류를 나타냅니다. 나는 인증 서비스 여기

System.Net Error: 0 : [9040] Exception in HttpWebRequest#46890055::GetResponse - The remote server returned an error: (500) Internal Server Error.. 

에 의해 허용되지 않았기 때문에 이것이 내가 (모두 IP를 내가 서비스되지 않습니다) 또한

(ip.src == xxx.xxx.xxx.xx or ip.dst == xxx.xxx.xxx.xx) and ssl.handshake 

인증서 와이어 샤크에서 사용하고있는 필터입니다 가정 개인 키를 사용하지 않습니다. 필자는 TLS 설명서에서 필요하지 않아야한다고 가정합니다.

내 질문에 내가 왜 프로그램을 실행할 때 클라이언트 Hello/Server Hello wireshark가 표시되지 않거나 클라이언트 안녕을 시작하도록 클라이언트 바인딩을 구성해야합니까?

(나는 전문가가 내 질문에 대한 답을 알고있을 WCF 생각 때문에 나는 WCF 태그. 나는 서비스 바인딩의 컨트롤이 없기 때문에 내 솔루션은 WCF의 독립적 인 것) 그것은 당신이있어 무엇을 같은 소리

답변

2

SSL/TLS에서 클라이언트 측 인증서 인증을 사용하는 것이 설명됩니다.이 경우 사용하는 클라이언트 인증서에 SSL/TLS 핸드 셰이크를 완료하는 데 필요한 개인 키가 있어야합니다.

<security mode="Transport"> 
    <transport clientCredentialType="Certificate" /> 
</security> 

을 그리고 어떻게 당신이 ClientCertificate 동작을 사용하여 사용할 인증서를 찾으려면 그것을 말해 : 클라이언트를 구성 할 때, 당신은 운송 인증을 위해 클라이언트 인증서를 사용하도록 바인딩을 말할 필요가

주의 사항 : 인증서는 클라이언트가로드 할 수있는 개인 키를 반드시 가질 키 지정하는 것이

<behaviors> 
    <endpointBehaviors> 
    <behavior name="ClientCertificateBehavior"> 
     <clientCredentials> 
     <clientCertificate findValue="CN=clienttempcert" storeLocation="CurrentUser" 
      storeName="My" x509FindType="FindBySubjectDistinguishedName" /> 
     </clientCredentials> 
    </behavior> 
    </endpointBehaviors> 
</behaviors> 

공지 사항 (서비스는, 그러나, 개인 키 전혀 필요하지 않습니다).

+0

이것은 내가 분명하지 않은 부분입니다. 브라우저를 통해 인증서를 다운로드하라는 메시지가 표시되고 다운로드 한 인증서에 개인 키가 없습니다. 인증서를 열면 "이 인증서는 다음 용도로 사용됩니다. * 원격 컴퓨터의 ID 유지 * 원격 컴퓨터에 ID 확인" 나에게 신원을 증명하기 위해 인증서를 서비스에 제공하는 것만 보입니다. 그런 다음 암호화는 내가 제공 한 wiki 링크에 설명 된 4 단계를 통해 발생합니다. – aelstonjones

+0

https 사이트를 방문 할 때 브라우저가 동일한 메커니즘을 사용한다고 가정합니다. 브라우저는 개인 키를 가지지 않지만 통신은 결국 암호화됩니다. – aelstonjones

+0

어디에서 인증서를 다운로드하고 있습니까? 인증 기관에서 온 것인가? 일반적으로 CA (인증 기관)에서 새 인증서를 생성하는 경우 CA는 개인 키를 가져 오거나 생성하지 않습니다. 개인 키는 요청이있는 컴퓨터에서만 생성 된 다음 인증서가 일치 할 때 키와 일치합니다. 같은 컴퓨터에 다시 다운로드하십시오. – tomasr

0

PFX를 가져 와서 서버 인증서에 설치하십시오. 개인 상점 또는 현재 상점, 지역 기계 상점 등

다음이 asp.net web.config에서 사용하고 findbyThumbPrint를 사용하십시오.

<behaviors> 
    <endpointBehaviors> 
    <behavior name="ClientCertificateBehavior"> 
     <clientCredentials> 
     <clientCertificate findValue="yourthumprinthere" storeLocation="CurrentUser" or PersonalStore 
      storeName="My" x509FindType="FindByThumbprint" /> 
     </clientCredentials> 
    </behavior> 
    </endpointBehaviors> 
</behaviors> 
관련 문제