2011-03-27 21 views
13

que he leído a través de muchas de las preguntas sobre ASP.NET MVC [RequireHttps] - pero no puedo encontrar la respuesta a esta pregunta: ¿MVC RequireHttps y redirigir si no https

¿cómo hacer que la atribuyen [RequireHttps] conmutar el url a https si no era https para empezar?

tengo este código:

public ActionResult DoSomething() 
{ 
    return View("AnotherAction"); 
} 

[RequireHttps] 
public ActionResult AnotherAction() 
{ 
    return View(); 
} 

Pero consigo un error que dice: "El recurso solicitado sólo se puede acceder a través de SSL."

El proyecto de futuros MVC tiene un atributo similar [RequireSsl(Redirect = true)]. Pero eso está desactualizado ahora ... ¿Cuál es el equivalente en MVC 2?

Cuando alguien escribe la URL http://example.com/home/dosomething o la url http://example.com/home/anotheraction, los necesito para ser redirigido a la URL http s: //example.com/home/anotheraction

editar esta es la secuencia de eventos:

Se llama a la URL http://example.com/home/dosomething desde otro sitio web. Redirigen a sus usuarios a esta url (con un response.redirect o similar).

DoSomething() luego intenta devolver AnotherAction(), pero falla con el mensaje de error "El recurso solicitado solo se puede acceder a través de SSL".

+0

Puede escribir un atributo personalizado para hacer eso. –

Respuesta

19

El atributo RequiresHttps intenta automáticamente redirigir al https://your-url. Me verificado este comportamiento en un sitio tengo que utiliza ese atributo, y también mirar el código de reflector:

protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext) 
{ 
    if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) 
    { 
     throw new InvalidOperationException(MvcResources.RequireHttpsAttribute_MustUseSsl); 
    } 
    string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl; 
    filterContext.Result = new RedirectResult(url); 
} 

¿Seguro de que haya establecido su sitio para aceptar conexiones seguras? ¿Qué ocurre si intenta navegar directamente al https://your-url?

+19

en realidad como muestra el código anterior, solo redirige las solicitudes GET. Si aparece una solicitud POST (o HEAD, etc.), simplemente arrojará la excepción.Una distinción importante – arserbin3

+1

Otra consecuencia es que cualquier acción del controlador que tenga [RequireHttps] y se acceda a través de GET también debe tener el atributo [HttpGet] para evitar la excepción cuando se envía una solicitud HEAD antes/en lugar de su contraparte GET. –

13

[MVC 4] respuesta corta:

protected void Application_BeginRequest(Object source, EventArgs e) 
{ 
    if (!Context.Request.IsSecureConnection) 
    { 
     Response.Redirect(Request.Url.AbsoluteUri.Replace("http://", "https://")); 
    } 
} 

ya la respuesta:
para mover de http a https usted no puede enviar una redirección a https después de que el primer paquete,
para ello tienes que coger el paquete utilizando Application_BeginRequest,
del Global.asax añadir la función y se anulará el valor predeterminado,
el código debe ser algo así como lo que (Global.asax en el nivel de clase):

protected void Application_BeginRequest(Object source, EventArgs e) 
{ 
    if (!Context.Request.IsSecureConnection && 
     !Request.Url.Host.Contains("localhost") && 
     Request.Url.AbsolutePath.Contains("SGAccount/Login")) 
    { 
     Response.Redirect(Request.Url.AbsoluteUri.Replace("http://", "https://")); 
    } 
} 

sugiero poner un punto de interrupción e inspeccionar el objeto Request.Url para cualquier necesidad relacionada con la url.
o visite el msdn page confundido acerca de request.url absoluteuri vs originalstring?
así que si puedes ir a dotnetperls para ver ejemplos.
esta función le permite desarrollar en localhost e implementar su código como está.
ahora, para cada página que desea hacer una redirección de https, debe especificarla en la condición if.
para pasar de https a http, puede usar la Respuesta regular.Redirigir este modo:

if (Request.Url.Scheme.Contains("https")) 
{ 
    Response.Redirect(string.Format("http://{0}", Request.Url.Authority), true); 
} 

aviso de esto también de apoyo que trabajan en el mismo código en el desarrollo de host local al no interrumpir el curso original de las cosas previamente la adición https.

También recomiendo pensar en la aplicación de algunas convenciones de retorno url (si no está ya implementado) en ese caso, debería ser algo así:

if (Request.Url.Scheme.Contains("https")) 
{ 
    Response.Redirect(string.Format("http://{0}{1}", Request.Url.Authority, returnUrl), true); 
} 

este redirigirá a la página de inicio de sesión solicitado puesto.

, naturalmente, debe proteger cada página que muestra datos de usuario, registro, inicio de sesión y más.

+0

Buscar cadena "localhost" podría no funcionar siempre; podría renombrarse. Consulte este tema similar con mi respuesta explicando [cómo manejar HTTPS solo para producción] (http://stackoverflow.com/a/38244992/1095493) con el uso de buil-in RequireHttpsAttribute dentro de Startup.cs (MVC 6). –

0

Para complementar la respuesta ya dada, este es el código de la aplicación MVC 5 de HandleNonHttpsRequest

protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext) 
{ 
    // only redirect for GET requests, otherwise the browser might not propagate the verb and request 
    // body correctly. 
    ... 
} 
2

MVC4 hace ahora redirigir

pero no la forma en que se puede esperar.

http://www.example.com:8080/alpha/bravo/charlie?q=quux habrá redirigir el navegador del cliente para https://www.example.com/alpha/bravo/charlie?q=quux

aviso de la falta de un número de puerto.

http://aspnetwebstack.codeplex.com/SourceControl/latest#test/System.Web.Mvc.Test/Test/RequireHttpsAttributeTest.cs código de prueba [Hecho] pública OnAuthorizationRedirectsIfRequestIsNotSecureAndMethodIsGet vacío()

confirma que este es el comportamiento deseado.

Si desea escribir un atributo personalizado que hace incluir el puerto ... puede basar su código en:

http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/RequireHttpsAttribute.cs

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] 
public class RequireHttpsAttribute : FilterAttribute, IAuthorizationFilter 
{ 
    public RequireHttpsAttribute() 
     : this(permanent: false) 
    { 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="RequireHttpsAttribute"/> class. 
    /// </summary> 
    /// <param name="permanent">Whether the redirect to HTTPS should be a permanent redirect.</param> 
    public RequireHttpsAttribute(bool permanent) 
    { 
     this.Permanent = permanent; 
    } 

    /// <summary> 
    /// Gets a value indicating whether the redirect to HTTPS should be a permanent redirect. 
    /// </summary> 
    public bool Permanent { get; private set; } 

    public virtual void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext == null) 
     { 
      throw new ArgumentNullException("filterContext"); 
     } 

     if (!filterContext.HttpContext.Request.IsSecureConnection) 
     { 
      HandleNonHttpsRequest(filterContext); 
     } 
    } 

    protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext) 
    { 
     // only redirect for GET requests, otherwise the browser might not propagate the verb and request 
     // body correctly. 

     if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) 
     { 
      throw new InvalidOperationException(MvcResources.RequireHttpsAttribute_MustUseSsl); 
     } 

     // redirect to HTTPS version of page 
     string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl; 
     filterContext.Result = new RedirectResult(url, this.Permanent); 
    } 
} 
3

Http CABEZA no aparecen solicita que se le redirigido Al revisar nuestros registros de errores que ver un montón de este mensaje, buscando en Google tierras aquí, pero después de mirar más en los detalles tienen algunas "características" interesantes

  • REQUEST_METHOD: CABEZA
  • Agente de usuario: rizos/7.35.0

En otras palabras, todos los intentos fallidos no eran de cara al cliente ...

(100% de crédito para comentar de @ arserbin3 para hacer que me diera cuenta que estaban todos HEAD solicitudes)

Cuestiones relacionadas