2011-10-06 22 views
17

¡Primera pregunta!Obtener url original sin puerto no estándar (C#)


Medio Ambiente

MVC, C#, AppHarbor.

Problema

Estoy llamando a un proveedor de OpenID, y generar una URL de devolución de llamada absoluta basada en el dominio.

en mi máquina local, esto funciona bien si golpeo http://localhost:12345/login

Request.Url; //gives me `http://localhost:12345/callback` 

Sin embargo, en AppHarbor donde estoy despliegue, porque están utilizando puertos no estándar, incluso si estoy golpeando al "http://sub.example.com/login"

Request.Url; //gives me http://sub.example.com:15232/callback 

Y esta tornillos hasta mi devolución de llamada, debido a que el número de puerto no estaba en la URL de la fuente original!

He intentado

  • Request.Url
  • Request.Url.OriginalString
  • Request.RawUrl

Todo a mi "http://sub.example.com:15232/callback" da.

también para aclarar que esto no es un problema de Realm, el mensaje de error que estoy recibiendo de DotNetOpenAuth es

'http://sub.example.com:14107/accounts/openidcallback' not under realm 'http://*.example.com/'. 

No creo que he de peluche que pasa?

ahora, estoy a punto de tener en cuenta algunas cosas como hacky

  • comandos del preprocesador (#IF DEBUG luego poner puerto)
  • cadena de reemplazo (Request.URL.Contains ("localhost"))

Todas estas soluciones no son del 100%, pero estoy cansado de reflexionar sobre lo que podría ser una propiedad simple que me falta. También he leído this pero eso no parece tener una respuesta aceptada (y se trata más de la ruta que de la autoridad). Así que lo estoy planteando para ustedes, chicos.

Resumen

Así que si tuviera http://localhost:12345/login, que necesita para obtener http://localhost:12345/callback del contexto de la petición.

Y si tuviera "http://sub.example.com/login", debería obtener "http://sub.example.com/callback", independientemente de en qué puerto esté.

Gracias!(Tiempo de sueño, responderá a cualquier pregunta en la mañana)

Respuesta

20

Este es un problema común en las configuraciones de carga equilibradas como AppHarbor de - hemos proporcionado un example workaround.

Actualización: Una solución más deseable para muchas aplicaciones ASP.NET puede ser configurar aspnet:UseHostHeaderForRequestUrl appSetting en true. Nosotros (AppHarbor) hemos visto a varios clientes experimentar problemas al usarlo con sus aplicaciones WCF, por lo que no lo hemos habilitado por defecto y aún recomendamos la solución anterior para esas situaciones. Puede configurarlo usando las "Variables de configuración" de AppHarbor para inyectar las aplicaciones cuando se implementan. Se puede encontrar más información en this article.

0

Mis pensamientos iniciales son obtener la variable de referencia y comprobar si eso incluye un puerto, si es así usarlo de lo contrario no lo haga.

Si no es una opción porque un proxy puede eliminar la variable de encabezado de referencia, entonces es posible que necesite utilizar algún script del lado del cliente para obtener la ubicación y pasarla de nuevo al servidor.

Supongo que AppHarbor utiliza el reenvío de puertos al servidor IIS, por lo que aunque públicamente el sitio está en el puerto 80, IIS lo tiene alojado en otro puerto, por lo que no puede saber en qué puerto se conectó el cliente.

+0

Terminé usando UrlReferrer (esto no tiene el puerto por alguna razón GRR!), Pero su mensaje me llevó hacia allí. No estoy seguro de ninguna ramificación, pero gracias de todos modos :) –

+0

¿Intentó utilizar algún javascript para obtener el puerto? podrías pasarlo en la cadena de consulta o publicarlo de nuevo. – Robert

+0

Eso es bastante hacky, no es algo en lo que quiera confiar. –

0

Algo así como

String port = Request.ServerVariables["SERVER_PORT"] == "80" ? "" : ":" + Request.ServerVariables["SERVER_PORT"]; 
String virtualRoot = Url.Content("~/"); 
destinationUrl = String.Format("http://{0}{1}{2}", Request.ServerVariables["SERVER_NAME"], port + virtualRoot, "/callback"); 
+0

Esto también eliminará el puerto en mi instancia localhost. :( –

1

Recientemente me encontré con un problema donde comparé una URL con la URL actual, y luego seleccioné la navegación basada en eso. Funcionó localmente, pero no en producción.

Tenía http://example.com/path/to/file.aspx como mi archivo, pero al visualizar ese archivo y ejecutar Request.Url.ToString() produjo https://example.com:81/path/to/file.aspx en un entorno de producción con carga equilibrada.

Ahora estoy usando Request.Url.AbsolutePath para simplemente darme /path/to/file.aspx, ignorando así el esquema, el nombre de host y los números de puerto.

cuando tengo que compararlo con la URL de cada elemento de navegación utilicé: New Uri(theLink.Href).AbsolutePath

0

Si se utiliza la clase UrlBuilder en el marco puede easly evitar esto. En la clase constructor si se configura el puerto a -1, entonces el número de puerto será removido:

new UriBuilder("http://sub.example.com:15232/callback"){ Port = -1} 

devuelve: http://sub.example.com/callback

Para mantener el número de puerto en un equipo local sólo comprobar Request.IsLocal y don no aplica -1 al puerto.

Me gustaría envolver esto en un método de extensión para mantenerlo limpio.

0

Veo que este es un hilo viejo. Tuve este problema ejecutando MVC5, en IIS 7.5, con un proxy Apache en el frente. Fuera del servidor, obtendría "Respuesta vacía", ya que la aplicación asp.net obtiene la URL de apache con el puerto personalizado.

Para que la aplicación redirija a un subtrayecto sin incluir el puerto "personalizado", olvide los objetos de respuesta/solicitud y utilice el método de transferencia.Por ejemplo, si quiero que los usuarios son redirigidos automáticamente a la página de inicio de sesión en caso de que no se registran ya:

if (!User.Identity.IsAuthenticated) 
    Server.TransferRequest("Account/Login"); 
Cuestiones relacionadas