Catch-22, WIF tarafından güvenli hale getirilen akışlı TCP WCF hizmetini önler; Noelimi mahvetmek, ruh sağlığı


181

WIF kullanarak akışlı bir WCF net.tcp hizmet uç noktasını güvence altına almak için bir gereksinimim var . Jeton sunucumuza karşı gelen çağrıların kimliğini doğrulamalıdır. Hizmet, büyük miktarlarda veri ve şeyleri aktarmak için tasarlandığından akışa sahiptir.

Bu imkansız görünüyor. Ve yakalamanın etrafında gidemezsem, Noel'im mahvolur ve neşeli alışverişçiler yavaş yavaş serinleyen vücuduma adım atarken kendimi bir olukta içeceğim. Çok ciddi çocuklar.

Bu neden imkansız? İşte Catch-22.

İstemcide, token sunucumuzdan aldığım GenericXmlSecurityToken ile bir kanal oluşturmam gerekiyor . Problem yok.

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

"Sorun yok" mu dedim? Problemo. Aslında, NullReferenceExceptionstil problemo.

"Dostum," diye sordum Çerçeveye, "boş kontrol bile ediyor musun?" Çerçeve sessizdi, bu yüzden demonte ettim ve

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

istisnanın kaynağıydı ve GetPropertyçağrı geri dönüyordu null. Peki, WTF? İleti güvenliğini açar ve istemci kimlik bilgilerini türüne ayarlarsam, IssuedTokenbu özelliğin artık ClientFactory(protip: IChannel'de, "piç" SetProperty "eşdeğeri yok) olduğunu gösterir.

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

Tatlı. Artık NRE yok. Ancak, şimdi müvekkilim doğumda hatalı (hala onu seviyorum, tho). WCF teşhisi yoluyla kazmak (protip: en kötü düşmanlarınızı ezdikten ve sizden önce sürdükten sonra yapın, ancak kadınlarının ve çocuklarının ağıtlarının tadını çıkarmadan hemen önce), bunun sunucu ve istemci arasındaki güvenlik uyumsuzluğu nedeniyle olduğunu görüyorum.

İstenen yükseltme 'net.tcp: // localhost: 49627 / MyService' tarafından desteklenmiyor. Bunun nedeni eşleşmeyen bağlamalar olabilir (örneğin sunucuda değil istemcide etkinleştirilmiş güvenlik).

Ana bilgisayarın dialarını kontrol etmek (tekrar: ezmek, sürmek, günlükleri okumak, ağıtların tadını çıkarmak), bunun doğru olduğunu görüyorum

Protokol Türü application / ssl-tls, bu tür yükseltmeyi desteklemeyen bir hizmete gönderildi.

"Şey, ben," dedim, "Ben sadece ev sahibi Mesaj güvenliğini açacağım!" Ve biliyorum. Nasıl göründüğünü bilmek istiyorsanız, istemci yapılandırmasının tam bir kopyasıdır. Yukarı Bak.

Sonuç: Kaboom.

Bağlama ('NetTcpBinding', ' http://tempuri.org/ '), ileti düzeyi güvenliği ile birlikte yapılandırılamayan akışı destekler. Farklı bir aktarım modu seçmeyi veya aktarım seviyesi güvenliğini seçmeyi düşünün.

Bu nedenle, sunucum jetonlarla hem aktarılamaz hem de güvence altına alınamaz . 22'yi yakala.

tl; dr: WIF kullanarak akışlı bir net.tcp WCF uç noktasını nasıl güvence altına alabilirim?


3
Tamam, muhtemelen cahil bir soru var, ama WIF gerçekten Mesaj modu gerektiriyor mu? Aktarım modu, akışla daha iyi çalışacak gibi görünüyor, açıkça test edilmemiş gibi<security mode="Transport" /> <transport clientCredentialType="IssuedToken" /> </security>
Joachim Isaksson

3
TransportWithMessageCredentialmod başka bir seçenek olabilir.
Joachim Isaksson

3
TMLK, MessageSecurity, tamponlu yükü imzalayabilir ve şifreleyebilir, ancak akışlarla uğraşırken boğulur. AuthenticationMode = IssuedTokenOverTransport kullanmayı düşündünüz mü?
OnoSendai

7
O zaman tatilinizi kurtarmak için geçmişten bazı hayaletler çağırabilir miyim bakayım. Burada bazı ipuçları: social.msdn.microsoft.com/Forums/vstudio/en-US/…
OnoSendai

2
Başkalarının deneyebileceği bir test senaryosu projesi yayınlama şansınız var mı?
antiduh

Yanıtlar:


41

WCF, ön kimlik doğrulamasının, çoğu insanın çalışması gerektiğini düşündüğü şekilde nasıl gerçekleştirilemediğiyle ilgili temel bir sorun nedeniyle akışla (size bakıyorum, MTOM 1 ) birkaç alanda yakalandı (yalnızca bu kanal için sonraki istekleri etkiler) , ilk istek değil) Tamam, bu tam olarak sizin sorununuz değil ama sonunda sizinkine ulaşacağım için lütfen takip edin. Normalde HTTP sorunu şu şekilde çalışır:

  1. istemci sunucuya anonim olarak vurur
  2. Sunucu diyor ki, üzgünüm, 401, kimlik doğrulamasına ihtiyacım var
  3. istemci sunucuya kimlik doğrulama jetonuyla vurur
  4. sunucu kabul eder.

Şimdi, sunucudaki bir WCF uç noktasında MTOM akışını etkinleştirmeyi denerseniz, şikayet etmeyecektir. Ancak, istemci proxy'de yapılandırdığınızda (gerektiği gibi, bağlayıcılarla eşleşmeleri gerekir) ateşli bir ölümle patlayacaktır. Bunun nedeni, WCF'nin önlemeye çalıştığı yukarıdaki olay dizisinin şudur:

  1. istemci tek bir POST'ta anonim olarak sunucuya 100MB dosya akışı yapar
  2. Sunucu özür dilerim, 401, kimlik doğrulamasına ihtiyacım var
  3. istemci bir kimlik doğrulama üstbilgisi ile sunucuya 100MB dosya aktarıyor
  4. sunucu kabul eder.

Yalnızca 100 MB göndermeniz gerektiğinde sunucuya 200 MB gönderdiğinizi unutmayın. Sorun bu. Yanıt, kimlik doğrulamayı ilk denemede göndermektir, ancak özel bir davranış yazmadan WCF'de bu mümkün değildir. Her neyse, konuya giriyorum.

Senin sorunun

Öncelikle, denediğiniz şeyin imkansız olduğunu söyleyeyim 2 . Şimdi, tekerleklerinizi döndürmeyi bırakmanız için size nedenini söyleyeyim:

Şu anda benzer bir problem sınıfında dolaştığınıza dikkat çekiyor. İleti düzeyinde güvenliği etkinleştirirseniz, istemcinin iletiyi ws-security için gereken olağan karma işlevi ve xml imzasıyla gerçekten kapatmadan önce tüm veri akışını belleğe yüklemesi gerekir. Tek bir iletiyi imzalamak için tüm akışı okuması gerekiyorsa (bu gerçekten bir ileti değildir, ancak tek bir sürekli akıştır) o zaman sorunu burada görebilirsiniz. WCF'nin ileti güvenliğini hesaplamak için bir kez "yerel" olarak akış yapması ve ardından sunucuya göndermek için yeniden akış yapması gerekir. Bu açıkça aptalca bir şeydir, bu nedenle WCF veri akışı için mesaj düzeyinde güvenliğe izin vermez.

Bu nedenle, buradaki basit yanıt, jetonu ilk web hizmetine parametre olarak veya bir SOAP başlığı olarak göndermeniz ve doğrulamak için özel bir davranış kullanmanızdır. Bunu yapmak için WS-Security'yi kullanamazsınız. Açıkçası, bu sadece bir WCF sorunu değil - diğer yığınlar için pratik olarak nasıl çalışabileceğini göremiyorum.

MTOM Sorununu Çözme

Bu sadece temel kimlik doğrulaması için MTOM akış sorunumu nasıl çözdüğümün bir örneğidir, bu yüzden belki de bunun cesaretini alabilir ve sorununuz için benzer bir şey uygulayabilirsiniz. Bunun en önemli özelliği, özel ileti denetçinizi etkinleştirmek için, taşıma düzeyinden (SSL) ayrı olarak istemci proxy'deki (sunucuda etkin kalır) tüm güvenlik kavramını devre dışı bırakmanız gerektiğidir:

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

Aktarım güvenliğini burada kapattığımı, çünkü kendime bir ileti denetçisi ve özel davranış kullanarak sağlayacağımı unutmayın:

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;
    }
}

Bu nedenle, bu örnek MTOM sorunuyla karşı karşıya olan herkes için değil, aynı zamanda birincil WIF korumalı token hizmeti tarafından oluşturulan tokeninizi doğrulamak için benzer bir şey uygulamanız için bir iskelet olarak.

Bu yardımcı olur umarım.

(1) Büyük Veri ve Akış

(2) WCF'de Mesaj Güvenliği (bkz. "Dezavantajlar").


MTOM and Basic Authorizationve MTOM ve OAuth2 ?
Kiquenet
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.