2009-07-18 25 views
5

Estoy trabajando en una aplicación web Silverlight v3 y me gustaría tener acceso seguro al servicio WCF que estoy utilizando para recuperar mis datos. Actualmente tengo el WCF funcionando bien, pero no requiere credenciales de usuario.WCF + Credenciales del usuario

No tengo mucha experiencia con este aspecto de WCF, así que mi primera idea fue agregar parámetros de nombre de usuario y contraseña para cada una de las operaciones de mi servicio. El problema que tengo con esto es que esto requeriría una gran cantidad de código redundante, y el hecho de que el nombre de usuario y la contraseña se transferirían a través del cable en texto plano.

Lo que me gustaría es una forma de especificar las credenciales por adelantado en el lado del cliente justo después de crear mi proxy de servicio (estoy usando el proxy autogenerado desde "Agregar referencia de servicio").

Al buscar en Google una solución para esto, solo pude encontrar soluciones similares a mi primera idea (usando los parámetros de nombre de usuario/contraseña). ¿Podría alguien señalarme en la dirección correcta?

Gracias!

Respuesta

7

¿Dónde están estos nombres de usuario y contraseñas procedentes de? Si su sitio web ya implementa la autenticación de Formularios, puede omitir el establecimiento de credenciales usted mismo y usar la cookie de autenticación de formularios.Si sus usuarios han iniciado sesión, la cookie viajará con la llamada al servicio web. Para leerlo del otro lado, necesitas hacer un par de cambios.

Primero necesita habilitar el modo de compatibilidad para ASP.NET de WCF en la sección system.serviceModel:

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

Una vez hecho esto entonces para cada método de servicio se quiere entender la cookie ASP.NET añadir el [AspNetCompatibilityRequirements] atribuye a su clase de servicio

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

Ahora dentro de cada método que se puede acceder al objeto HttpContext.Current.User.Identity para descubrir la identidad del usuario.

Si sólo desea ciertos métodos a ser llamados por los usuarios autenticados a continuación, se puede utilizar un PrincipalPermission tanto

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

Como beneficio adicional si está utilizando proveedor de funciones de ASP.NET este caso, también se rellenarán y a continuación, puede utilizar un PrincipalPermission sobre los métodos para limitar a los miembros de un papel particular:

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

Y esto funciona en Silverlight2 así obviamente.

+0

Se ve bien; ¿Sabes por casualidad si esto (o algo similar) se puede utilizar si se utiliza httpwebrequest sin formato? Tengo una pila de RPC personalizada que me gustaría asegurar de la misma manera (por supuesto, puedo preguntar como un nuevo queston si es una respuesta no trivial) –

+0

Debería hacer sí; ver http://www.silverlightshow.net/items/Cookies-in-Silverlight-Web-Requests.aspx – blowdart

+0

Ta; Voy a ver eso ;-p –

0

puede pasar algún tipo de objeto de autenticación y cifrarlo en el nivel de mensajes con WCF. Los aspectos C# (http://www.postsharp.org/) se pueden usar para evitar la lógica redundante. Es una forma muy limpia de manejarlo.

1

No mueva el suyo y añada parámetros explícitos, ¡de hecho, es demasiado trabajo!

Eche un vistazo a las características de seguridad de WCF, ¡hay muchas disponibles! Puede, por ejemplo, asegure el mensaje e incluya las credenciales dentro del mensaje; ¡todo listo, no se requiere codificación adicional de su lado!

Control hacia fuera este excelente artículo sobre la seguridad de WCF por Michele Leroux Bustamante: http://www.devx.com/codemag/Article/33342

En su caso, sugeriría seguridad de los mensajes con las credenciales Nombre de usuario - es necesario configurar esto en ambos extremos:

del lado del servidor:

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

Y tiene que aplicar la misma configuración en el lado del cliente:

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

Ahora su servidor y el cliente están de acuerdo en la seguridad - en el cliente, que le especifique el nombre de usuario y contraseña para usar como esto:

YourServiceClient client = new YourServiceClient(); 

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

En el lado del servidor, necesitará para configurar cómo se validan estas credenciales de usuario, generalmente contra un dominio de Windows (Active Directory) o contra el modelo de proveedor de membresía de ASP.NET. En cualquier caso, si las credenciales del usuario no se pueden verificar contra esa tienda que usted defina, la llamada será rechazada.

Espero que esto ayude un poco - la seguridad es un gran tema en WCF y tiene muchas opciones - puede ser un poco desalentador, pero al final, ¡generalmente tiene sentido! :-)

Marc

+6

No estoy seguro de qué escenario fue capaz de hacer esto, pero en mi experiencia, esto no está permitido en WCF. No se puede usar la seguridad de nombre de usuario y credencial de modo de mensaje en basicHttpBinding, no está permitido por el marco porque las credenciales se pasarán en texto sin formato. Obtendrá esta InvalidOperationException: "El enlace BasicHttp requiere que BasicHttpBinding.Security.Message.ClientCredentialType sea equivalente al tipo de credencial BasicHttpMessageCredentialType.Certificate para los mensajes seguros. Seleccione Transport o TransportWithMessageCredential security para las credenciales UserName." – Grank

Cuestiones relacionadas