121 votes

ASP.NET MVC RequireHttps en production uniquement

Je veux utiliser le RequireHttpsAttribute pour empêcher les requêtes HTTP non sécurisées d'être envoyées à une méthode d'action.

C#

[RequireHttps] //apply to all actions in controller
public class SomeController 
{
    [RequireHttps] //apply to this action only
    public ActionResult SomeAction()
    {
        ...
    }
}

VB

<RequireHttps()> _
Public Class SomeController

    <RequireHttps()> _
    Public Function SomeAction() As ActionResult
        ...
    End Function

End Class

Malheureusement, le serveur de développement ASP.NET ne prend pas en charge le HTTPS.

Comment puis-je faire en sorte que mon application ASP.NET MVC utilise RequireHttps lorsqu'elle est publiée dans l'environnement de production, mais pas lorsqu'elle est exécutée sur mon poste de travail de développement sur le serveur de développement ASP.NET ?

129voto

Joel Mueller Points 14985

Cela n'aidera pas si vous exécutez les builds Release sur votre station de travail de développement, mais la compilation conditionnelle pourrait faire l'affaire...

#if !DEBUG
[RequireHttps] //apply to all actions in controller
#endif
public class SomeController 
{
    //... or ...
#if !DEBUG
    [RequireHttps] //apply to this action only
#endif
    public ActionResult SomeAction()
    {
    }

}

Mise à jour

En Visual Basic, les attributs font techniquement partie de la même ligne que la définition à laquelle ils s'appliquent. Vous ne pouvez pas insérer de déclarations de compilation conditionnelle à l'intérieur d'une ligne, ce qui vous oblige à écrire la déclaration de fonction deux fois - une fois avec l'attribut et une fois sans. Mais cela fonctionne, si vous n'êtes pas gêné par la laideur.

#If Not Debug Then
    <RequireHttps()> _
    Function SomeAction() As ActionResult
#Else
    Function SomeAction() As ActionResult
#End If
        ...
    End Function

Mise à jour 2

Plusieurs personnes ont mentionné le fait de dériver de RequireHttpsAttribute sans fournir d'exemple, alors en voici un pour vous. Je pense que cette approche serait beaucoup plus propre que l'approche de la compilation conditionnelle, et ce serait ma préférence dans votre position.

AVERTISSEMENT : Je n'ai pas testé ce code, même un tout petit peu, et mon VB est assez rouillé. Tout ce que je sais, c'est qu'il compile. Je l'ai écrit en me basant sur les suggestions de spot, queen3, et Lance Fisher. S'il ne fonctionne pas, il devrait au moins transmettre l'idée générale, et vous donner un point de départ.

Public Class RemoteRequireHttpsAttribute
    Inherits System.Web.Mvc.RequireHttpsAttribute

    Public Overrides Sub OnAuthorization(ByVal filterContext As  _
                                         System.Web.Mvc.AuthorizationContext)
        If IsNothing(filterContext) Then
            Throw New ArgumentNullException("filterContext")
        End If

        If Not IsNothing(filterContext.HttpContext) AndAlso _
            filterContext.HttpContext.Request.IsLocal Then
            Return
        End If

        MyBase.OnAuthorization(filterContext)
    End Sub

End Class

En gros, le nouvel attribut s'arrête au lieu d'exécuter le code d'autorisation SSL par défaut, si la requête en cours est locale (c'est-à-dire si vous accédez au site via localhost). Vous pouvez l'utiliser comme suit :

<RemoteRequireHttps()> _
Public Class SomeController

    <RemoteRequireHttps()> _
    Public Function SomeAction() As ActionResult
        ...
    End Function

End Class

Beaucoup plus propre ! A condition que mon code non testé fonctionne réellement.

65voto

mikesl Points 983

Si quelqu'un a besoin de la version C# :

using System;
using System.Web.Mvc;

namespace My.Utils
{
    public class MyRequireHttpsAttribute : RequireHttpsAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            if (filterContext.HttpContext != null && filterContext.HttpContext.Request.IsLocal)
            {
                return;
            }

            base.OnAuthorization(filterContext);
        }
    }
}

26voto

Lance Fisher Points 13547

Dériver de RequireHttps est une bonne approche.

Pour contourner complètement le problème, vous pouvez utiliser IIS sur votre machine locale avec un certificat auto-signé également. IIS est plus rapide que le serveur Web intégré, et vous avez l'avantage que votre environnement de développement ressemble davantage à un environnement de production.

Scott Hanselman propose une excellente ressource sur les différentes manières de mettre en œuvre le HTTPS local avec VS2010 et IIS Express.

12voto

gt124 Points 704

En tirant parti du système de filtres MVC et de Global.asax.cs, je suppose que vous pourriez faire ceci...

    protected void Application_Start()
    {
      RegisterGlobalFilters(GlobalFilters.Filters);
    }

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
      filters.Add(new HandleErrorAttribute());
      if(Config.IsProduction) //Some flag that you can tell if you are in your production environment.
      {
        filters.Add(new RequireHttpsAttribute());
      }
    }

10voto

Samuel Jack Points 14556

Comme c'est le serveur de développement ASP.Net qui est à l'origine de votre problème, il est intéressant de noter que Microsoft a maintenant IIS Express qui est livré avec Visual Studio (depuis VS2010 SP1). Il s'agit d'une version réduite d'IIS qui est aussi facile à utiliser que le serveur de développement, mais qui prend en charge l'ensemble des fonctionnalités d'IIS 7.5, y compris SSL.

Scott Hanselman a publié un article détaillé sur Travailler avec SSL dans IIS Express .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X