2009-07-18 9 views
5

Ich arbeite an einer Silverlight v3-Webanwendung und möchte den Zugriff auf den WCF-Dienst sichern, den ich zum Abrufen meiner Daten verwende. Ich habe derzeit die WCF funktioniert gut, aber es erfordert keine Benutzeranmeldeinformationen.WCF + Benutzeranmeldeinformationen

Ich bin nicht sehr erfahren mit diesem Aspekt von WCF, also war meine erste Idee, Benutzernamen und Passwort-Parameter zu jedem Service meines Dienstes hinzuzufügen. Das Problem, das ich damit habe, ist, dass dies viel redundanten Code erfordern würde, und die Tatsache, dass der Benutzername und das Passwort im Klartext über die Leitung übertragen würden.

Was ich möchte ist eine Möglichkeit, die Anmeldeinformationen direkt auf der Client-Seite direkt nach der Erstellung meines Service-Proxy (Ich verwende den Proxy automatisch generiert von "Add Service Reference") zu spezifizieren.

Beim googlen nach einer Lösung konnte ich nur Lösungen finden, die meiner ersten Idee ähnlich sind (benutze Benutzername/Passwort-Parameter). Könnte mir bitte jemand in die richtige Richtung zeigen?

Danke!

Antwort

7

Woher kommen diese Benutzernamen und Passwörter? Wenn Ihre Website die Formularauthentifizierung bereits implementiert, können Sie die Anmeldeinformationen selbst umgehen und den Cookie für die Formularauthentifizierung verwenden.Wenn Ihre Benutzer angemeldet sind, wird der Cookie mit dem Web-Service-Aufruf übertragen. Um es auf der anderen Seite zu lesen, müssen Sie ein paar Änderungen vornehmen.

Zuerst müssen Sie ASP.NET-Kompatibilitätsmodus für WCF im System.ServiceModel Abschnitt aktivieren:

<system.serviceModel> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
</system.serviceModel> 

Sobald das getan wird dann für jede Service-Methode Sie wollen verstehen, die ASP.NET Cookie hinzufügen [AspNetCompatibilityRequirements]

[ServiceContract] 
[AspNetCompatibilityRequirements(
    RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
public class ExampleService 
{ 
} 

Nun zu Ihrem Service-Klasse-Attribut innerhalb jeder Methode können Sie das HttpContext.Current.User.Identity Objekt zugreifen die Identität des Benutzers zu entdecken.

Wenn Sie nur bestimmte Methoden wollen von authentifizierten Benutzern aufgerufen werden, dann können Sie damit

[OperationContract] 
[PrincipalPermission(SecurityAction.Demand, Authenticated=true)] 
public string Echo() 

Als Bonus ein Principal verwenden, wenn Sie ASP.NET Rolle Provider verwenden dann auch gefüllt werden diejenigen wird und Sie können dann eine Principal auf Methoden verwenden, um sie zu Mitgliedern einer bestimmten Rolle zu begrenzen: auch offensichtlich

[OperationContract] 
[PrincipalPermission(SecurityAction.Demand, Role="Administators")] 
public string NukeTheSiteFromOrbit() 

Und das funktioniert in Silverlight2.

+0

Sieht gut aus; Wissen Sie zufällig, ob dies (oder etwas Ähnliches) verwendbar ist, wenn Sie raw httpwebrequest verwenden? Ich habe einen benutzerdefinierten RPC-Stack, den ich auf die gleiche Weise sichern möchte (ich kann natürlich als neue Frage fragen, ob es eine nicht-triviale Antwort ist) –

+0

Es sollte ja sein; siehe http://www.silverlightshow.net/items/Cookies-in-Silverlight-Web-Requests.aspx – blowdart

+0

Ta; Ich schaue mir das an ;-p –

0

Sie können eine Art Authentifizierungsobjekt übergeben und auf Nachrichtenebene mit WCF verschlüsseln. C# -Aspekte (http://www.postsharp.org/) können dann verwendet werden, um redundante Logik zu vermeiden. Es ist eine sehr saubere Art, es zu handhaben.

1

Rollen Sie nicht Ihre eigenen und fügen Sie explizite Parameter hinzu - das ist in der Tat viel zu viel Arbeit!

Überprüfen Sie die WCF-Sicherheitsfunktionen - viele davon verfügbar! Sie können z.B. Sichern Sie die Nachricht und fügen Sie die Anmeldeinformationen in die Nachricht ein - alles aus der Box, keine zusätzliche Codierung auf Ihrer Seite erforderlich!

prüft diese ausgezeichneten Artikel über WCF Sicherheit heraus von Michele Leroux Bustamante: http://www.devx.com/codemag/Article/33342

In Ihrem Fall würde ich die Nachrichtensicherheit mit Benutzername Credentials vorschlagen - Sie diese an beiden Enden konfigurieren müssen:

Server-Seite:

<bindings> 
    <basicHttpBinding> 
    <binding name="SecuredBasicHttp" > 
     <security mode="Message"> 
     <message clientCredentialType="UserName"/> 
     </security> 
    </binding> 
    </basicHttpBinding> 
</bindings> 
<services> 
    <service name="YourService"> 
    <endpoint address="http://localhost:8000/MyService" 
       binding="basicHttpBinding" 
       bindingConfiguration="SecuredBasicHttp" 
       contract="IYourService" /> 
    </service> 
</services> 

Und Sie müssen die gleichen Einstellungen auf der Client-Seite gelten:

<bindings> 
    <basicHttpBinding> 
    <binding name="SecuredBasicHttp" > 
     <security mode="Message"> 
     <message clientCredentialType="UserName"/> 
     </security> 
    </binding> 
    </basicHttpBinding> 
</bindings> 
<client> 
    <endpoint address="http://localhost:8000/MyService" 
       binding="basicHttpBinding" 
       bindingConfiguration="SecuredBasicHttp" 
       contract="IYourService" /> 
</client> 

Jetzt Ihren Server und Client auf die Sicherheit zustimmen - auf dem Client, würden Sie dann den Benutzernamen und das Passwort wie folgt zu verwenden:

YourServiceClient client = new YourServiceClient(); 

client.ClientCredentials.UserName.UserName = "your user name"; 
client.ClientCredentials.UserName.Password = "top$secret"; 

Auf der Server-Seite, die Sie benötigen Festlegen, wie diese Benutzeranmeldeinformationen überprüft werden - in der Regel entweder gegen eine Windows-Domäne (Active Directory) oder gegen das ASP.NET-Mitgliedschaftsanbietermodell. Wenn die Benutzeranmeldeinformationen nicht für den von Ihnen definierten Speicher überprüft werden können, wird der Aufruf abgelehnt.

Hoffe, das hilft ein bisschen - Sicherheit ist ein großes Thema in WCF und hat viele Optionen - es kann ein wenig entmutigend sein, aber am Ende macht es normalerweise Sinn! :-)

Marc

+6

Ich bin mir nicht sicher, in welchem ​​Szenario Sie dies tun konnten, aber nach meiner Erfahrung ist dies in WCF nicht erlaubt. Sie können die Anmeldesicherheit für Benutzernamen im Anmeldemodus nicht in basicHttpBinding verwenden. Sie wird vom Framework nicht zugelassen, da die Anmeldeinformationen im Nur-Text-Format übergeben werden. Sie erhalten diese InvalidOperationException: "Die BasicHttp-Bindung erfordert, dass BasicHttpBinding.Security.Message.ClientCredentialType dem Credentials-Typ BasicHttpMessageCredentialType.Certificate für sichere Nachrichten entspricht. Wählen Sie Transport oder TransportWithMessageCredential-Sicherheit für UserName-Anmeldedaten." – Grank

Verwandte Themen