2010-09-02 12 views
25

Quiero mi página de inicio de sesión sea única SSL:ASP.NET MVC: ¿Cómo deshabilitar automáticamente [RequireHttps] en localhost?

[RequireHttps] 
    public ActionResult Login() 
    { 
     if (Helper.LoggedIn) 
     { 
      Response.Redirect("/account/stats"); 
     } 

     return View(); 
    } 

Pero es obvio que no funciona en el servidor local cuando desarrollo y depurar mi aplicación. No quiero usar IIS 7 con certificados SSL, ¿cómo puedo desactivar automáticamente el atributo RequireHttps?

actualización

Sobre la base de información proporcionada por los usuarios stackoverflow y ASP.NET MVC 2 código fuente creé la siguiente clase que resuelve el problema.

public class RequireSSLAttribute : FilterAttribute, IAuthorizationFilter 
{ 
    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) 
    { 
     if (filterContext.HttpContext.Request.Url.Host.Contains("localhost")) return; 

     if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) 
     { 
      throw new InvalidOperationException("The requested resource can only be accessed via SSL"); 
     } 

     string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl; 
     filterContext.Result = new RedirectResult(url); 
    } 
} 

y se usa así:

[RequireSSL] 
public ActionResult Login() 
{ 
    if (Helper.LoggedIn) 
    { 
     Response.Redirect("/account/stats"); 
    } 

    return View(); 
} 
+0

Si usted busca desbordamiento de pila de "RequireHttps" la cuestión se ha pedido un par de veces, por lo que una gran cantidad de información con respecto a la solución. Sin embargo, es una buena pregunta, no he usado ese atributo todavía, pero puedo ver que es un problema de inmediato. –

+0

Tienes razón. El problema ha sido resuelto y actualicé mi publicación principal con la clase que me ayudó. – Alex

Respuesta

25

Lo más fácil sería para derivar un nuevo atributo de RequireHttps y anular HandleNonHttpsRequest

protected override void HandleNonHttpsRequest(AuthorizationContext filterContext) 
     { 
      if (!filterContext.HttpContext.Request.Url.Host.Contains("localhost")) 
      { 
       base.HandleNonHttpsRequest(filterContext); 
      } 
     } 

HandleNonHttpsRequest es el método que arroja la excepción, aquí todo lo que estamos haciendo no es llamar si el host es localhost (y como dice Jeff en su comentario podría extender esto a entornos de prueba o, de hecho, cualquier otra excepción que desee).

+0

Este método podría modificarse para que tampoco requiera HTTPS en entornos de prueba. –

+0

¿Dónde debería colocar este código? Actualización Oh, no importa, tengo esto. – Alex

+0

Utilicé su código y el código fuente de MVC para crear una solución. ¡Gracias! – Alex

14
#if (!DEBUG) 
[RequireHttps] 
#endif 
public ActionResult Login() 
{ 
    if (Helper.LoggedIn) 
    { 
     Response.Redirect("/account/stats"); 
    } 

    return View(); 
} 
+2

Pensé en esto también. Pero significa que tengo que agregar #if DEBUG para cada atributo RequireHttps. – Alex

+0

ah, pensé que era solo una ocasión. Las otras propuestas son mejores entonces. – Femaref

8

Puede encapsular este requisito en un atributo derivado:

class RequireHttpsNonDebugAttribute : RequireHttpsAttribute { 
    public override void HandleNonHttpsRequest(AuthorizationContext ctx) { 
     #if (!DEBUG) 
     base.HandleNonHttpsRequest(ctx); 
     #endif 
    } 
} 
17
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { 

     if (!HttpContext.Current.IsDebuggingEnabled) { 
      filters.Add(new RequireHttpsAttribute()); 
     } 
    } 
+0

Sería más útil agregar un poco de información sobre dónde colocar este código, solo para ayudar a aquellos que no están familiarizados con ASP.NET MVC. – Andrew

+4

En mi proyecto actual de MVC, había un archivo predeterminado en la carpeta App_Start llamado FilterConfig.cs. Agrégalo allí. – fabspro

1

MVC 6 (ASP.NET Core 1.0):

La solución adecuada sería utilizar env.IsProduction() o env.IsDevelopment().

Ejemplo:

Startup.cs - AddMvc con un filtro personalizado:

public void ConfigureServices(IServiceCollection services) 
{ 
    // TODO: Register other services 

    services.AddMvc(options => 
    { 
     options.Filters.Add(typeof(RequireHttpsInProductionAttribute)); 
    }); 
} 

personalizado hereda filtro de decisiones RequireHttpsAttribute

public class RequireHttpsInProductionAttribute : RequireHttpsAttribute 
{ 
    private bool IsProduction { get; } 

    public RequireHttpsInProductionAttribute(IHostingEnvironment environment) 
    { 
     if (environment == null) 
      throw new ArgumentNullException(nameof(environment)); 
     this.IsProduction = environment.IsProduction(); 
    } 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (this.IsProduction) 
      base.OnAuthorization(filterContext); 
    } 
    protected override void HandleNonHttpsRequest(AuthorizationContext filterContext) 
    { 
     if(this.IsProduction) 
      base.HandleNonHttpsRequest(filterContext); 
    } 
} 

Diseño explicó:

  1. Use el entorno IsProduction() o IsDevelopment() sobre, p. Ej. "#if DEBUG". Algunas veces lanzamos/publicamos en modo DEPURAR en nuestro servidor de prueba y no queremos deshabilitar este requisito de seguridad. Esto necesita ser desactivado solo en localhost/development (ya que somos demasiado flojos para configurar localhost SSL en IIS Express o lo que sea que usemos localmente).
  2. Utilice el filtro en Startup.cs para la configuración global (ya que queremos que esto se aplique en todas partes). Startup debe ser responsable de registrar y configurar todas las reglas globales. Si su empresa emplea un nuevo desarrollador, esperaría encontrar la configuración global en Startup.cs.
  3. Use RequireHttpsAttribute lógica ya que está probado (por Microsoft). Lo único que queremos cambiar es cuando se aplica la lógica (producción) y cuándo no (desarrollo/host local). Nunca utilice cadenas "mágicas" como "http: //" y "https: //" cuando se pueda evitar reutilizando un componente de Microsoft creado para proporcionar la misma lógica.

Por encima de Yo consideraría la solución "adecuada".

Nota:

Como alternativa , podríamos hacer una "clase BaseController: Controller" y hacer que todos nuestros controladores heredan de "BaseController" (en lugar del controlador). Entonces solo tenemos que establecer el atributo 1 lugar global (y no es necesario registrar el filtro en Startup.cs).

Algunas personas prefieren el estilo de atributo. Tenga en cuenta que esto eliminará los beneficios de la decisión de diseño # 2.

Ejemplo de uso:

[RequireHttpsInProductionAttribute] 
public class BaseController : Controller 
{ 
    // Maybe you have other shared controller logic.. 
} 

public class HomeController : BaseController 
{ 
    // Add endpoints (GET/POST) for Home controller 
} 
Cuestiones relacionadas