2013-12-19 1 views
179

나는 WIF을 사용하여 스트리밍 된 WCF net.tcp 서비스 끝점을 보안해야한다는 요구 사항이 있습니다. 우리의 토큰 서버에 대해 들어오는 호출을 인증해야합니다. 이 서비스는 많은 양의 데이터를 전송하도록 설계되었으므로 스트리밍됩니다.Catch-22는 WIF로 보안 설정할 수있는 스트리밍 된 TCP WCF 서비스를 방지합니다. 내 크리스마스, 정신 건강 망치

이것은 불가능한 것처럼 보입니다. 그리고 내가 잡을 수 없다면 크리스마스가 망가질 것이고, 메리 쇼퍼가 천천히 몸을 차게하는 동안 나 자신을 마시고 죽을 것이다. 토트 중독, 너희들.

왜 이것이 불가능합니까? 여기에 Catch-22가 있습니다.

클라이언트에서 토큰 서버에서 가져온 GenericXmlSecurityToken으로 채널을 만들어야합니다. 문제 없습니다.

// people around here hate the Framework Design Guidelines. 
var token = Authentication.Current._Token; 
var service = base.ChannelFactory.CreateChannelWithIssuedToken(token); 
return service.Derp(); 

"문제 없음"이라고 했습니까? 문제. 사실, NullReferenceException 스타일 문제.

"형,"프레임 워크에 "너는 null 검사까지 해?"라고 물었습니다. 프레임 워크는 침묵했다, 그래서 나는 분해

((IChannel)(object)tChannel). 
    GetProperty<ChannelParameterCollection>(). 
    Add(federatedClientCredentialsParameter); 

예외의 원인이라고하고 GetProperty 호출 null을 반환하는 것을 발견했다. 그래서, WTF? 메일 보안을 사용 설정하고 클라이언트 자격증 명 유형을 IssuedToken으로 설정하면이 속성은 이제 ClientFactory에 존재합니다. (protip : IChannel에 해당하는 "SetProperty"가 없습니다.

<binding name="OMGWTFLOL22" transferMode="Streamed" > 
    <security mode="Message"> 
     <message clientCredentialType="IssuedToken"/> 
    </security> 
</binding> 

스위트. 더 이상 NRE가 아닙니다. 그러나, 지금 나의 클라이언트는 출생시 오류 (여전히 그를, tho 사랑)입니다. WCF 진단을 통해 파문을 일으킨다. (protip : 최악의 적을 해치 우고 여자와 아이들의 애도를 즐기기 전에 우연히 만난다.) 서버와 클라이언트 사이의 보안 불일치 때문이다.

'net.tcp : // localhost : 49627/MyService'에서 요청한 업그레이드가 지원되지 않습니다. 이는 일치하지 않는 바인딩 (예 : 클라이언트가 아닌 서버에서 사용할 수있는 보안) 때문일 수 있습니다. 나는 볼이하지 않는 서비스로 전송 된

프로토콜 유형 응용 프로그램/SSL-TLS 사실이다 :

호스트의 DIAGS을 (짝사랑, 예레미야 애가를 즐길 로그를 읽을 드라이브, 다시) 확인 해당 유형의 업그레이드를 지원하십시오.

"글쎄, 자기,"나는 "호스트에서 메시지 보안을 켜기 만 할 것입니다!"라고 말합니다. 그리고 나는 그렇다. 모양을 알기 원하면 클라이언트 구성의 정확한 사본입니다. 찾다.

결과 : Kaboom.

는 ('NetTcpBinding', 'http://tempuri.org/')를 결합하여 메시지 레벨 보안을 함께 구성 할 수없는 스트리밍을 지원.다른 전송 모드를 선택하거나 전송 레벨 보안을 선택하십시오.

그래서, 내 호스트는 모두 스트리밍 및 토큰를 통해 확보 할 수 없습니다. Catch-22.

tl; dr : WIF를 사용하여 스트리밍 된 net.tcp WCF 끝점을 보호하려면 어떻게해야합니까 ???

+3

좋아, 아마 무지 질문을 여기지만 WIF 정말 메시지 모드를 필요로 하는가? 전송 모드는 스트리밍과 같이 잘 작동하지 않는 것처럼 들리는데, 분명히 테스트되지 않은 ' –

+3

['TransportWithMessageCredential'] (http : // msdn.microsoft.com/en-us/library/ms731884(v=vs.110).aspx) 모드가 다른 옵션 일 수 있습니다. –

+0

@JoachimIsaksson : 메시지 보안을 전혀 사용할 수 없습니다. – Will

답변

41

WCF가이 사전 인증을 대부분의 사람들이 그 일을해야 생각하는 방법을 수행하지 못한 방법으로 인해 근본적인 문제에 스트리밍 몇 지역에서 개는 (내가 당신을 찾고 있어요 MTOM 1)가 (그것을 첫 번째 요청이 아닌 해당 채널에 대한 후속 요청에만 영향을줍니다.) 그래,이 문제는 정확하게 문제가 아니지만 끝까지 따라갈 것입니다. 일반적으로 HTTP의 과제는 다음과 같이 작동

  1. 클라이언트는 익명으로
  2. 서버 죄송합니다, (401), 나는 인증
  3. 클라이언트가
  4. 서버가 받아 토큰 인증 서버 안타 필요 말한다 서버를 안타.

이제 서버의 WCF 끝점에서 MTOM 스트리밍을 사용하도록 설정하면 불평하지 않습니다. 그러나 클라이언트 프록시에서 구성 할 때 (바인딩과 일치해야 함) 불타는 죽음에서 폭발하게됩니다. 그 이유는 WCF 방지하려고하는 이벤트의 위의 순서가이 때문이다 :

  1. 클라이언트가 익명으로 하나의 POST
  2. 서버에서 서버로 메가 바이트 파일을 스트림 (401), 죄송합니다라고, 나는 인증
  3. 필요
  4. 클라이언트가 인증 헤더가있는 서버에 100MB 파일을 다시 스트림합니다.
  5. 서버가 수락합니다.

100MB 만 보내야 할 때 서버에 200MB를 보냈습니다. 음, 이것이 문제입니다. 대답은 첫 번째 시도에서 인증을 보내는 것이지만 사용자 정의 동작을 작성하지 않고 WCF에서는 가능하지 않습니다. 어쨌든, 나는 빗 나간다.

문제

첫번째로, 내가 당신이하려는 것은 2 불가능하다고 말할 수 있습니다. 이제 바퀴 회전을 멈추기 위해 이유를 알려 드리겠습니다.

비슷한 종류의 문제에서 방황하고 있습니다. 메시지 레벨 보안을 활성화하면 클라이언트는 ws-security에 필요한 일반적인 해시 함수 및 xml 서명을 사용하여 메시지를 실제로 닫을 수 있으려면 전체 데이터 스트림을 메모리에로드해야합니다. 단일 메시지에 서명하기 위해 전체 스트림을 읽어야하는 경우 (실제로는 메시지가 아니지만 단일 연속 스트림입니다) 여기에서 문제를 볼 수 있습니다. WCF는 메시지 보안을 계산하기 위해 한 번 "로컬"로 스트리밍 한 다음 다시 스트리밍하여 서버로 보냅니다. 이것은 분명히 어리석은 일이므로 WCF는 스트리밍 데이터에 대한 메시지 수준 보안을 허용하지 않습니다.

간단한 대답은 초기 웹 서비스의 매개 변수 또는 SOAP 헤더로 토큰을 보내고 유효성 검사를 위해 사용자 지정 동작을 사용해야한다는 것입니다.WS-Security를 ​​사용하여이를 수행 할 수 없습니다. 솔직히 말해서, 이것은 WCF 문제 만은 아닙니다. 다른 스택에 대해 실제로 어떻게 작동 하는지를 볼 수 없습니다. 그래서 아마 당신이 당신의 문제에 대한 비슷한이의 배짱을 가지고 구현할 수는 MTOM 문제

이 그냥 기본 인증에 대한 내 MTOM 스트리밍 문제를 해결하는 방법에 대한 예입니다 해결

.

this._contentService.Endpoint.Behaviors.Add(
    new BasicAuthenticationBehavior(
     username: this.Settings.HttpUser, 
     password: this.Settings.HttpPass)); 
var binding = (BasicHttpBinding)this._contentService.Endpoint.Binding; 
binding.Security.Mode = BasicHttpSecurityMode.Transport; // SSL only    
binding.Security.Transport.ClientCredentialType = 
    HttpClientCredentialType.None; // Do not provide 
: 그것의 핵심은 사용자 정의 메시지 관리자를 가능하게하기 위해, 당신이 떨어져 전송 수준 (SSL)에서 (이 서버에서 활성화 상태로 유지) 클라이언트 프록시에 대한 보안의 모든 개념을 사용하지 않도록해야한다는 것입니다 으로도

internal class BasicAuthenticationBehavior : IEndpointBehavior 
{ 
    private readonly string _username; 
    private readonly string _password; 

    public BasicAuthenticationBehavior(string username, string password) 
    { 
     this._username = username; 
     this._password = password; 
    } 
    public void AddBindingParameters(ServiceEndpoint endpoint, 
     BindingParameterCollection bindingParameters) { } 
    public void ApplyClientBehavior(ServiceEndpoint endpoint, 
     ClientRuntime clientRuntime) 
    { 
     var inspector = new BasicAuthenticationInspector(
      this._username, this._password); 
     clientRuntime.MessageInspectors.Add(inspector); 
    } 
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, 
     EndpointDispatcher endpointDispatcher) { } 
    public void Validate(ServiceEndpoint endpoint) { } 
} 

internal class BasicAuthenticationInspector : IClientMessageInspector 
{ 
    private readonly string _username; 
    private readonly string _password; 

    public BasicAuthenticationInspector(string username, string password) 
    { 
     this._username = username; 
     this._password = password; 
    } 

    public void AfterReceiveReply(ref Message reply, 
     object correlationState) { } 

    public object BeforeSendRequest(ref Message request, 
     IClientChannel channel) 
    { 
     // we add the headers manually rather than using credentials 
     // due to proxying issues, and with the 101-continue http verb 
     var authInfo = Convert.ToBase64String(
      Encoding.Default.GetBytes(this._username + ":" + this._password)); 

     var messageProperty = new HttpRequestMessageProperty(); 
     messageProperty.Headers.Add("Authorization", "Basic " + authInfo); 
     request.Properties[HttpRequestMessageProperty.Name] = messageProperty; 

     return null; 
    } 
} 

그래서,이 예제는 MTOM 문제로 고통 받고 사람입니다,하지만 : 나는 나 자신이 메시지 관리자 및 사용자 정의 동작을 사용하는 것을 제공 할 수 있기 때문에 여기에 전송 보안을 꺼져

주 기본 WIF 보안 토큰 서비스가 생성 한 토큰을 인증하는 것과 유사한 기능을 구현할 수있는 골격.

희망이 도움이됩니다.

(1) Large Data and Streaming

(2) Message Security in WCF ("단점"을 참조하십시오.)