2010-09-02 4 views
25

Je veux que ma page de connexion SSL pour être seulement:ASP.NET MVC: Comment désactiver automatiquement [RequireHttps] sur localhost?

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

     return View(); 
    } 

Mais évidemment, il ne fonctionne pas sur localhost quand je développe et déboguer mon application. Je ne veux pas utiliser IIS 7 avec des certificats SSL, comment puis-je désactiver automatiquement l'attribut RequireHttps?

Mise à jour

Sur la base des informations fournies par les utilisateurs StackOverflow et le code source ASP.NET MVC 2 J'ai créé la classe suivante qui résout le problème.

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); 
    } 
} 

Et il est utilisé comme ceci:

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

    return View(); 
} 
+0

Si vous recherchez Stack Overflow pour « RequireHttps » la question a été posée plusieurs fois, donc beaucoup d'informations sur la solution. C'est une bonne question cependant, je n'ai pas encore utilisé cet attribut mais je peux voir que c'est un problème tout de suite. –

+0

Vous avez raison. Le problème a été résolu et j'ai mis à jour mon post principal avec la classe qui m'a aidé. – Alex

Répondre

25

La meilleure chose serait d'obtenir un nouvel attribut de RequireHttps et passer outre HandleNonHttpsRequest

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

HandleNonHttpsRequest est la méthode jette l'exception, ici tout ce que nous faisons ne l'appelle pas si l'hôte est localhost (et comme Jeff dit dans son commentaire que vous pourriez étendre cela aux environnements de test ou en fait toutes les autres exceptions que vous voulez).

+0

Cette méthode peut être modifiée pour ne pas nécessiter le protocole HTTPS dans les environnements de test. –

+0

Où dois-je placer ce code? Mise à jour Oh, peu importe, j'ai compris. – Alex

+0

J'ai utilisé votre code et le code source de MVC pour créer une solution. Merci! – Alex

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

    return View(); 
} 
+2

J'ai aussi pensé à ça. Mais cela signifie que je dois ajouter #if DEBUG pour chaque attribut RequireHttps. – Alex

+0

ah, je pensais que c'était seulement une occasion. Les autres propositions sont meilleures alors. – Femaref

8

Vous pouvez résumer cette exigence dans un attribut dérivé:

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

Il serait plus utile d'ajouter un peu d'informations concernant où placer ce code, juste pour aider ceux qui ne sont pas familiers avec ASP.NET MVC. – Andrew

+4

Dans mon projet MVC actuel, il y avait un fichier par défaut dans le dossier App_Start appelé FilterConfig.cs. Ajoutez-le là. – fabspro

1

MVC 6 (ASP.NET 1.0 de base):

La bonne solution serait d'utiliser env.IsProduction() ou env.IsDevelopment().

Exemple:

Startup.cs - AddMvc avec un filtre personnalisé:

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

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

Filtre personnalisé Hériter de 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); 
    } 
} 

Les décisions de conception explique:

  1. Utilisez l'environnement IsProduction() ou IsDevelopment() par ex. "#if DEBUG". Parfois, nous publions/publions en mode DEBUG sur notre serveur de test et ne voulons pas désactiver cette exigence de sécurité. Cela doit être désactivé uniquement dans localhost/development (puisque nous sommes trop paresseux pour installer SSL localhost dans IIS Express ou tout ce que nous utilisons localement).
  2. Utilisez le filtre dans Startup.cs pour l'installation globale (puisque nous voulons que cela s'applique partout). Le démarrage doit être responsable de l'enregistrement et de la configuration de toutes les règles globales. Si votre entreprise emploie un nouveau développeur, elle s'attend à trouver une configuration globale dans Startup.cs.
  3. Utilisez RequireHttpsAttribute logique car il est prouvé (par Microsoft). La seule chose que nous voulons changer est quand la logique est appliquée (production) et quand elle n'est pas (développement/localhost). N'utilisez jamais de chaînes "magiques" comme "http: //" et "https: //" quand elles peuvent être évitées en réutilisant un composant Microsoft créé pour fournir la même logique.

Ci-dessus, je considérerais la solution «appropriée».

Note:

En tant autre, nous pourrions faire une "classe BaseController: Controller" et que tous nos contrôleurs héritent de "BaseController" (au lieu de contrôleur). Il suffit ensuite de définir l'emplacement global de l'attribut 1 (et de ne pas enregistrer le filtre dans Startup.cs).

Certaines personnes préfèrent le style d'attribut. Veuillez noter que cela éliminera les avantages de la décision n ° 2.

Exemple d'utilisation:

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

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