Catch-22 zapobiega przesyłaniu strumieniowej usługi TCP WCF przez WIF;

Mam obowiązek zabezpieczyć sieć WCF.punkt końcowy usługi tcp przy użyciu WIF . Powinien on uwierzytelniać połączenia przychodzące na naszym serwerze tokena. Usługa jest przesyłana strumieniowo, ponieważ jest przeznaczona do przesyłania dużych ilości danych n rzeczy.

To wydaje się niemożliwe.Jeśli nie uda mi się obejść połowu, moje święta będą zrujnowane i wypiję się na śmierć w rynsztoku, podczas gdy merry shoppers nadepnie na moje powoli chłodzące ciało. Totes poważnie.

Dlaczego jest to niemożliwe? Tu jest haczyk-22.

Na kliencie, muszę utworzyć kanał z GenericXmlSecurityToken otrzymuję z naszego serwera tokena. Nie ma problemu.

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

Powiedziałem "no problemo"? Problemo. W rzeczywistości, NullReferenceException style problemo.

"brachu," zapytałem ramy, " czy ty w ogóle nie sprawdzasz?"Rama była cicha, więc zdemontowałem i stwierdziłem, że

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

Był źródłem wyjątku, i że [[4]} połączenie było zwracane null. WTF? Okazuje się, że jeśli włączę zabezpieczenie wiadomości i ustawię Typ poświadczenia klienta na IssuedToken wtedy ta właściwość już istnieje w ClientFactory (protip: nie ma odpowiednika "SetProperty" w IChannel, bękart).

<binding name="OMGWTFLOL22" transferMode="Streamed" >
    <security mode="Message">
        <message clientCredentialType="IssuedToken"/>
    </security>
</binding>
Słodko. Koniec z NREs. Jednak teraz mój klient jest winny przy urodzeniu (nadal go kocham, tho). Przekopując się przez diagnostykę WCF (protip: spraw, by Twoi najgorsi wrogowie robili to po zmiażdżeniu ich i przejechaniu ich przed tobą, ale tuż przed rozkoszowaniem się lamentami swoich kobiet i dzieci), widzę, że to z powodu niedopasowania bezpieczeństwa między serwerem a klientem.

Żądana aktualizacja nie jest obsługiwana przez 'net.tcp: / / localhost: 49627 / MyService". Może to być spowodowane niedopasowanymi powiązaniami (na przykład zabezpieczenia włączone na kliencie, a nie na serwerze).

Sprawdzanie diagów hosta (ponownie: crush, drive, read logs, enjoy lamentations), widzę, że to prawda

Typ protokołu aplikacja / ssl-TLS została wysłana do usługi, która nie obsługuje tego typu aktualizacji.

"cóż, self," mówię, " po prostu włączam zabezpieczenie wiadomości na gospodarzu!"I tak jest. jeśli chcesz wiedzieć, jak to wygląda, jest to dokładna kopia konfiguracji klienta. Spójrz w górę.

Wynik:

The binding ('NetTcpBinding', ' http://tempuri.org / ') obsługuje strumieniowanie, którego nie można skonfigurować wraz z zabezpieczeniem poziomu wiadomości. Rozważ wybór innego trybu transferu lub wybór poziomu bezpieczeństwa transportu.

Więc, mój host nie może być zarówno streamowany, jak i zabezpieczony za pomocą tokenów. Catch-22.

Tl; dr: Jak mogę zabezpieczyć streamowaną sieć.TCP WCF endpoint przy użyciu WIF???

Author: BoltClock, 2013-12-19

1 answers

WCF ma gotchas w kilku obszarach z streamingu (patrzę na Ciebie, MTOM1) ze względu na fundamentalny problem w jaki sposób nie wykonuje preautoryzacji w sposób, w jaki większość ludzi uważa, że powinno działać (wpływa to tylko na kolejne prośby o ten kanał, a nie pierwsze żądanie) Ok, więc nie jest to dokładnie twój problem, ale proszę podążać za nim, jak dojdę do twojego na końcu. Normalnie wyzwanie HTTP działa tak:

  1. klient atakuje serwer anonimowo
  2. serwer says, sorry, 401, I need authentication
  3. klient atakuje serwer tokenem uwierzytelniania
  4. serwer akceptuje.

Teraz, jeśli kiedykolwiek spróbujesz włączyć strumieniowanie MTOM na punkcie końcowym WCF na serwerze, nie będzie to narzekać. Ale, kiedy skonfigurujesz go na kliencie proxy (jak powinieneś, muszą dopasować wiązania) wybuchnie ognistą śmiercią. Powodem tego jest to, że powyższa sekwencja zdarzeń, którym WCF stara się zapobiec, jest następująca:

  1. client streams 100MB plik do serwera anonimowo w jednym poście
  2. serwer mówi Przepraszam, 401, potrzebuję uwierzytelnienia
  3. klient ponownie przesyła 100MB pliku do serwera z nagłówkiem uwierzytelniania
  4. serwer akceptuje.

Zauważ, że właśnie wysłałeś 200MB na serwer, gdy potrzebowałeś tylko wysłać 100MB. W tym problem. Odpowiedzią jest wysłanie uwierzytelnienia przy pierwszej próbie, ale nie jest to możliwe w WCF bez napisania niestandardowego zachowania. W Każdym Razie, Ja dygresja.

Twój Problem

Po pierwsze, powiem ci, że to, czego próbujesz, jest niemożliwe.2. A teraz, żebyś przestał kręcić kołami, powiem ci dlaczego: {]} Uderza mnie, że teraz błądzisz w podobnej klasie problemów. Jeśli włączysz zabezpieczenie poziomu wiadomości, Klient musi załadować cały strumień danych do pamięci, zanim będzie mógł faktycznie zamknąć wiadomość za pomocą zwykłej funkcji skrótu i podpisu xml wymaganego przez WS-security. Jeśli musi odczytać cały strumień, aby podpisać pojedynczą wiadomość (która tak naprawdę nie jest wiadomością, ale jest pojedynczym ciągłym strumieniem), możesz zobaczyć problem tutaj. WCF będzie musiał streamować go raz "lokalnie", aby obliczyć bezpieczeństwo wiadomości, a następnie streamować go ponownie, aby wysłać go do serwera. Jest to oczywiście niemądra rzecz, więc WCF nie pozwala na zabezpieczenie poziomu komunikatów dla strumieniowania danych.

Więc, prosta odpowiedź jest taka, że należy wysłać token albo jako parametr do początkową usługę internetową, lub jako nagłówek SOAP i użyć niestandardowego zachowania, aby ją zweryfikować. Nie możesz użyć WS-Security, aby to zrobić. Szczerze mówiąc, nie jest to tylko kwestia WCF - nie widzę, jak mogłoby to działać praktycznie dla innych stosów.

RozwiÄ…zanie problemu MTOM

To tylko dla przykładu, jak rozwiązałem problem streamingu MTOM dla podstawowego uwierzytelniania, więc być może mógłbyś wziąć to na siebie i zaimplementować coś podobnego dla Twojego problemu. Sednem tego jest to, że w aby włączyć niestandardowego Inspektora wiadomości, musisz wyłączyć wszystkie pojęcia bezpieczeństwa na serwerze proxy klienta (pozostaje on włączony na serwerze) oprócz poziomu transportu (SSL): {]}

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

Zauważ, że wyłączyłem tutaj ochronę transportu, ponieważ sam będę to zapewniał za pomocą Inspektora wiadomości i niestandardowego zachowania:

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

Więc ten przykład jest dla każdego, kto cierpi z powodu problemu MTOM, ale także jako szkielet dla ciebie, aby zaimplementować coś podobnego do Uwierzytelnij token wygenerowany przez podstawową usługę WIF-secured token service.

Mam nadzieję, że to pomoże.

(1) Duże Dane i przesyłanie strumieniowe

(2) Bezpieczeństwo wiadomości w WCF (patrz " wady.")

 41
Author: x0n,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-05 20:20:33