.net - example - wcf basic authentication username password
Autenticación de usuario/pase utilizando RESTful WCF y Windows Forms (4)
¿Cuál es el mejor enfoque para implementar la autorización / autenticación para una aplicación de Windows Forms que habla con un servicio RESTful WCF alojado en IIS?
La razón por la que pregunto es que estoy muy confundido, después de examinar diferentes artículos y publicaciones que expresan un método diferente y, finalmente, llegar a un documento de ~ 650 páginas sobre las mejores prácticas de seguridad de WCF "( http://www.codeplex.com/WCFSecurityGuide ). no estoy seguro de qué enfoque es MEJOR tomar y cómo comenzar la implementación, dada mi situación.
Comencé con este artículo "Una guía para diseñar y construir servicios web RESTful con WCF 3.5" ( http://msdn.microsoft.com/en-us/library/dd203052.aspx ) y un video de PDC sobre servicios RESTful WCF, que fue excelente y me ayudó a implementar mi primer servicio WCF apto para REST,
Después de que tuve el servicio funcionando, volví a implementar la seguridad, ver. "Consideraciones de seguridad" (un cuarto en la página) e intentó implementar un encabezado de Autorización HTTP según las instrucciones, sin embargo, encontré que el código está incompleto (vea cómo nunca se declaró la variable ''UserKeys''). Este es el punto en el que traté de investigar más sobre cómo hacer esto (usando un hash HMAC con el encabezado HTTP "Authorization", pero no pude encontrar mucho en google?) Me llevó a otros artículos sobre seguridad a nivel de mensajes, formularios auth y validadores personalizados y, francamente, no estoy seguro de cuál es el enfoque mejor y más apropiado para tomar ahora.
Entonces, con todo lo dicho (¡y gracias por escuchar hasta ahora!), Creo que mis preguntas principales son:
- ¿Qué implementación de seguridad debo usar?
- ¿Hay alguna forma de evitar enviar el nombre de usuario / contraseña con cada llamada WCF? Preferiría no enviar estos bytes adicionales si se ha establecido una conexión al principio, que será antes de que se puedan realizar llamadas posteriores después del inicio de sesión.
- ¿Debo preocuparme realmente por algo más que texto plano si estoy usando SSL?
Como dije, la aplicación de formularios .NET 3.5 win, servicio WCF alojado en IIS, sin embargo, lo que es importante es que todos y cada uno de los servicios de WCF requieran este procedimiento de autorización (como sea, sesión, encabezado http u otro) ya que no quiere que cualquiera pueda acceder a estos servicios desde la web.
Sé que la publicación anterior es grande, pero tuve que expresar la ruta que ya tuve y lo que necesito lograr, cualquier ayuda es muy apreciada.
PD: también conozco esta publicación Cómo configurar servicios RESTful seguros con WCF usando nombre de usuario / contraseña + SSL y si la comunidad sugiere que me aleje de REST para servicios de WCF, puedo hacerlo, sin embargo comencé con esto para mantener la coherencia para cualquier API pública por venir.
Creo que es importante que diga cómo estoy accediendo a mi Servicio WCF (el servicio de contacto está funcionando, pero ¿cuál es la mejor manera de validar las credenciales y luego devolver el objeto Miembro?):
WebChannelFactory<IMemberService> cf = new WebChannelFactory<IMemberService>(
new Uri(Properties.Settings.Default.MemberServiceEndpoint));
IMemberService channel = cf.CreateChannel();
Member m = channel.GetMember("user", "pass");
Código que se implementó a medias desde el artículo de MS (y algunos de los míos para pruebas):
public Member GetMember(string username, string password)
{
if (string.IsNullOrEmpty(username))
throw new WebProtocolException(HttpStatusCode.BadRequest, "Username must be provided.", null);
if (string.IsNullOrEmpty(password))
throw new WebProtocolException(HttpStatusCode.BadRequest, "Password must be provided.", null);
if (!AuthenticateMember(username))
{
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
return null;
}
return new Member() { Username = "goneale" };
}
Bueno, no tengo ninguna experiencia con las capacidades REST de WCF, pero luché mucho para comprender las implicaciones de las opciones de seguridad en mi pregunta de seguridad WCF . Como habrán notado, hay una falta real de documentación sobre WCF en su web, y mi experiencia REST es limitada, así que tome mis respuestas con un grano de sal:
¿Qué implementación de seguridad debo usar?
y
¿Debo preocuparme realmente por algo más que texto simple si estoy usando SSL?
La autenticación básica sobre SSL está bien, después de todo, esta es la forma en que una gran cantidad de sitios web existentes autentican a los usuarios. (Cuando inicia sesión en su cuenta de Amazon, solo están transmitiendo su nombre de usuario y contraseña a medida que la escribió a través de una conexión SSL.) Entiendo lo que dice el artículo sobre seguridad y ataques de diccionario, pero bla, bla, bla, manténgalo simple y obtener algo que funcione primero. Plain Old XML API de UPS pregunta por el nombre de usuario y la contraseña con cada llamada, también lo hace la API POX de FedEx, también lo hace la API SOAP de PayPal y la API SOAP de CyberSource; esto parece ser lo suficientemente bueno para el uso en el mundo real.
¿Hay alguna manera de evitar enviar el nombre de usuario / contraseña con cada llamada WCF? Preferiría no enviar estos bytes adicionales si se ha establecido una conexión al principio, que será antes de que se puedan realizar llamadas posteriores después del inicio de sesión.
Este es uno al que puedo responder con un poco más de confianza. Por lo general, tratamos de diseñar nuestros servicios públicos de WCF para que sean apátridas. De esta forma, nuestros servicios de WCF se escalan fácilmente; solo tira más hardware y más servidores y equilibradores de carga al problema, y no tenemos que preocuparnos por las sesiones adhesivas o por mantener el estado de la sesión en algún lugar. Entonces eso significa que si queremos "mantener un usuario conectado", entonces no es algo que va a suceder en el servidor.
Lo que terminé haciendo es tratar mi sitio web como un subsistema de confianza. Se autenticó contra el servicio WCF utilizando un certificado X509 precompartido, y si un cliente iniciaba sesión en el sitio web a través de la Autenticación de formularios, enviaba un encabezado de nombre de usuario del cliente al servicio; un comportamiento de punto final personalizado en el servicio WCF buscará este encabezado, verá que fue instalado por un subsistema de confianza y procederá a suplantar a ese usuario sin necesidad de que se proporcione o verifique la contraseña del usuario en la base de datos.
Como está utilizando REST, probablemente pueda usar una cookie en el lado del cliente para mantener el estado. Si usa el modo de compatibilidad ASP.NET, creo que incluso puede usar la Autenticación de formularios directamente, pero no sé mucho sobre este enfoque ya que mi servicio WCF no fue alojado en IIS.
En resumen, sin embargo, tendrá que enviar algo con cada solicitud para identificar al usuario, ya sea el nombre de usuario y la contraseña, solo el nombre de usuario o algún valor hash almacenado en la cookie. Si es la última opción, supongo que debe tener algún tipo de método de Login()
de Login()
o algo en el servicio, algo que envíe un "bueno, está registrado si pasa este valor hash con solicitudes futuras". Pero no todos los clientes de REST esperarán recibir cookies, solo solicitudes GET / PUT / POST / DELETE simples sin ningún estado.
Si esos fueran mis zapatos, elegiría el enfoque del subsistema de confianza (donde se proporciona un encabezado de nombre de usuario junto con las credenciales precompartidas para el subsistema) o exigiría la autenticación en cada llamada. El servicio probablemente obtendría algún mecanismo de caché de autenticación de alto rendimiento si todas esas solicitudes repetidas se convirtieran en un problema.
Espero que eso te ayude un poquito.
Bueno, realmente no deberías prestar tanta atención al lado de WinForms porque el lado de WCF es la clave.
Por cierto, ¿leíste cuidadosamente estas páginas?
y cómo http://www.codeplex.com/WCFSecurity/Wiki/View.aspx?title=How%20Tos&referringTitle=Home
Gracias por las respuestas. Dando un paso atrás y mirando clara e imparcialmente el problema en su conjunto (en otras palabras, ignorando las 4+ horas que invertí investigando los servicios RESTful) estoy intentando que la cosa funcione sin REST por ahora y las referencias que intento seguir en el momento son estos:
- http://blogs.msdn.com/pedram/archive/2007/10/05/wcf-authentication-custom-username-and-password-validator.aspx
- http://www.devatwork.nl/index.php/2007/05/31/wcf-username-authentication/
Esto parece aplicable para lo que quiero.
lextm: te oigo hablar de esto, después de escribir la publicación, examiné más de cerca la guía de seguridad de WCF e hice notas sobre todos mis requisitos en función de las opciones dadas en las que quieren que pienses en cada principio.
He elegido:
- Modo de seguridad de transferencia: seguridad de transporte
- Auth. Opción: Seguridad Básica
- Encuadernación: wsHttpBinding
- Autenticación personalizada con validador de nombre de usuario
A la luz de los ejemplos proporcionados para cada uno y mirando el caso de uso de formularios de Windows w / WCF, parece ser la mejor manera de hacerlo.
Nicholas: De acuerdo, diseñar los servicios para ser apátridas es probablemente un mejor enfoque.
Por lo tanto, según el artículo que seguiré cuando tenga tiempo, utiliza el certificado X509. para lo cual soy muy nuevo (entiendo que estás usando este Nicholas) ¿estará bien ya que esta aplicación cliente puede descargarse de Internet e instalarse en cualquier PC que tenga una cuenta en mi sitio web?
Saludos por toda tu ayuda, Graham
PD: Creo que este es el caso de uso más cercano a mi escenario (excepto que deseo usar la seguridad del transporte), ¿debería considerar implementar esto ya que no se molesta con un certificado? De la cita que leí, podría necesitar el certificado. como "WCF requiere el cifrado del certificado X509 porque las credenciales del cliente (nombre de usuario / contraseña) se pasan como texto claro en el mensaje SOAP". Sin embargo, por lo que he aprendido y lo que hemos dicho, si estoy usando SSL, ¿este punto probablemente sea discutible?
Usando autenticación básica:
WebHttpBinding binding = new WebHttpBinding();
binding.SendTimeout = TimeSpan.FromSeconds(25);
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
Uri address = new Uri("http://localhost:3525/WcfRestWeb/Quotes.svc");
WebChannelFactory<IQuoteService> factory =
new WebChannelFactory<IQuoteService>(binding, address);
factory.Credentials.UserName.UserName = "tan";
factory.Credentials.UserName.Password = "wani";
IQuoteService proxy = factory.CreateChannel();
var response = proxy.GenerateQuote(GetQuoteRequest());
Console.WriteLine("Quote Amount: " + response.QuoteAmount);