web-dev-qa-db-fra.com

redirection asp.net c # de http vers https

Donc, dans mon code, je veux détecter si ma page de connexion s'appelle http et la rediriger vers https.

Je sais qu'il existe des moyens non codés pour habiller ce chat, mais pour une raison technique frustrante, je suis obligé de le faire en code.

            if (!Request.IsSecureConnection)
            {
                string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
                Response.Redirect(redirectUrl);
            }

Donc je laisse tomber ceci dans ma Page_Load(...), m'assure que mon débogueur utilise le vrai IIS, pas le VS2008s IIS, et frappe le débogage.

Dans le débogueur, valsez, appuyez sur Response.Redirect (" https: //localhost/StudentPortal3G/AccessControl/AdLogin.aspx "), appuyez sur f5.

Obtenir "Internet Explorere ne peut pas afficher la page Web, l'URL est HTTP, pas HTTPS. Pas d'erreur informative ... la même chose se produit ne fonctionne pas dans le débogueur.

Alors qu'est-ce qui me manque? cela ne semble pas être de la science des fusées, j'ai vu un code similaire sur de nombreux blogs ...

Qu'est-ce que je fais mal? Je pense que ce doit être une erreur de recrue totalement évidente, mais je ne le vois pas.

49
Eric Brown - Cal

Je ferais aussi un !Request.IsLocal Pour m'assurer que je ne débogue pas, bien que si vous utilisez une instance réelle de IIS avec un certificat appliqué lors du débogage qui ne devrait pas être un problème.

if (!Request.IsLocal && !Request.IsSecureConnection)
{
    string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
    Response.Redirect(redirectUrl, false);
    HttpContext.ApplicationInstance.CompleteRequest();
}

Remarque: Cette réponse suppose un contexte MVC dans un contrôleur où HttpContext est une propriété contenant le contexte actuel. Si vous n'avez pas la chance de continuer à utiliser WebForms ou de référencer le contexte de manière dégénérée, vous devrez utiliser HttpContext.Current.ApplicationInstance.CompleteRequest().

Remarque: J'ai mis à jour cela pour être cohérent avec le modèle recommandé pour terminer la demande conformément à la documentation du framework .

Lorsque vous utilisez cette méthode dans un gestionnaire de pages pour terminer une demande pour une page et démarrer une nouvelle demande pour une autre page, définissez endResponse sur false, puis appelez la méthode CompleteRequest. Si vous spécifiez true pour le paramètre endResponse, cette méthode appelle la méthode End pour la demande d'origine, qui lève une exception ThreadAbortException lorsqu'elle se termine. Cette exception a un effet néfaste sur les performances des applications Web, c'est pourquoi il est recommandé de passer false pour le paramètre endResponse. Pour plus d'informations, voir la méthode End.

82
tvanfosson

J'appelle généralement les éléments suivants à partir de OnPreInit dans une classe de base dont toutes mes pages héritent. Bien sûr, vous pouvez simplement le faire dans chaque page ... mais vous ne voudriez pas le faire maintenant, n'est-ce pas?

Notez que j'ai deux propriétés pour chaque page afin que je puisse spécifier l'exigence SSL pour chaque page (RequiertSSL) tandis que je peux également remplacer et rediriger la vérification si je veux (avec IgnoreRequiresSSL, ce qui est utile pour les pages comme les pages d'erreur que vous réécrire et ne savent pas s'ils seront chiffrés ou non), mais bien sûr, vous pouvez les supprimer pour des configurations simples.

    protected override void OnPreInit(EventArgs e)
    {
        base.OnPreInit(e);

        if (!IsPostBack)
            RedirectAccordingToRequiresSSL();

        ...
    }

    /// <summary>
    /// Redirect if necessary to ssl or non-ssl enabled URL dependant on RequiresSSL property setting.
    /// </summary>
    private void RedirectAccordingToRequiresSSL()
    {
        if (IgnoreRequiresSSL) return;

        if (RequiresSSL)
        {
            if (!Request.IsSecureConnection) // Need to redirect to https
                RedirectAccordingToRequiresSSL(Uri.UriSchemeHttps);
        }
        else if (Request.IsSecureConnection)
        {
            RedirectAccordingToRequiresSSL(Uri.UriSchemeHttp);
        }

        // Otherwise don't need to do any redirecting as already using the correct scheme
    }

    /// <summary>
    /// Redirect as requested to specified scheme
    /// </summary>
    /// <param name="scheme"></param>
    private void RedirectAccordingToRequiresSSL(string scheme)
    {
        var url = scheme + Uri.SchemeDelimiter + Request.Url.Authority + Request.Url.PathAndQuery;
        Response.Redirect(url, false);
    }
24
Ted

À mon avis, ce qui suit est la meilleure approche globale.

Trois raisons

  1. Cela fonctionne pour MVC et Web API comme cela se fait au niveau IIS.
  2. Cela n'affecte pas les paramètres locaux/de débogage. (la redirection permanente peut vous déranger lors du débogage de sites non https sur votre PC).
  3. Utilise une redirection permanente, donc toutes les demandes futures iront automatiquement à https

Ajoutez simplement ce qui suit à votre <system.webServer> section dans votre 'Web.config' pour votre projet.

 <system.webServer>
 ....

 <rewrite>
  <rules>
    <rule name="HTTP to HTTPS redirect" stopProcessing="true">
      <match url="(.*)" />
      <conditions>
        <add input="{HTTP_Host}" pattern="localhost" negate="true" />
        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
      </conditions>
      <action type="Redirect" url="https://{HTTP_Host}/{R:1}" redirectType="Permanent" />
    </rule>
  </rules>
  <outboundRules>
    <rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
      <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
      <conditions>
        <add input="{HTTPS}" pattern="on" ignoreCase="true" />
      </conditions>
      <action type="Rewrite" value="max-age=31536000" />
    </rule>
  </outboundRules>
</rewrite>
</system.webServer>
9
Zapnologica

Vous pouvez également utiliser le nouveau UriBuilder:

Dim context As HttpContext = HttpContext.Current
If Not context.Request.IsSecureConnection Then
    Dim secureUrl As New UriBuilder(context.Request.Url)
    secureUrl.Scheme = "https"
    secureUrl.Port = 443
    context.Response.Redirect(secureUrl.ToString, False)
    Return
End If

C #

HttpContext context = HttpContext.Current;
if (!context.Request.IsSecureConnection)
{
    UriBuilder secureUrl = new UriBuilder(context.Request.Url);
    secureUrl.Scheme = "https";
    secureUrl.Port = 443;
    context.Response.Redirect(secureUrl.ToString(), false);
}
7

L'une des façons dont j'ai pu appliquer une redirection https est la suivante:

Dans le pool d'applications, mon application s'exécute uniquement sur le port 443 afin qu'il n'y ait aucune possibilité qu'une session non cryptée se produise (sauf si le schéma de cryptage est rompu par une vulnérabilité ..). J'ai créé une autre application sur le port 80 avec la même adresse IP qui contient juste un fichier web.config avec le code suivant

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
    <httpRedirect enabled="true" destination="https://yourWebsiteURL.com" />
</system.webServer>
3
Erkin Djindjiev

Je suggérerais également la solution de tvalfonsso, mais avec une petite modification au cas où vous auriez une réécriture d'URL (RawUrl diffère de Url)

    if (SPPage == SPPages.StartAutotrading && !Request.IsLocal && !Request.IsSecureConnection)
        {
            string redirectUrl = (Request.Url.ToString().Replace(Request.Url.PathAndQuery.ToString(), "") + Request.RawUrl).Replace("http:", "https:");
            Response.Redirect(redirectUrl);
        }
2
Robert Benyi

Voici ma solution:

// Force HTTPS connection
if (!Request.IsSecureConnection)
{
    var uri = new Uri(Request.Url.ToString());
    var redirectUrl = Settings.CanonicalDomain + uri.PathAndQuery;
    Response.Status = "301 Moved Permanently";
    Response.AddHeader("Location", redirectUrl);
    Response.End();
}

Settings.CanonicalDomain est votre nom d'hôte HTTPS. Il 301 redirige ce qui peut être la réponse appropriée dans certains cas.

2
Tom Gullen

Mentions légales - J'ai participé au développement de ce projet

Je recommanderais d'utiliser http://nuget.org/packages/SecurePages/ Il vous donne la possibilité de sécuriser des pages spécifiques ou d'utiliser Regex pour définir des correspondances. Il forcera également toutes les pages ne correspondant pas au Regex ou directement spécifiées à HTTP.

Vous pouvez l'installer via NuGet: Install-Package SecurePages

Les documents sont ici: https://github.com/webadvanced/Secure-Page-manager-for-asp.net#secure-pages

Utilisation simple:

SecurePagesConfiguration.Urls.AddUrl("/cart");

ou

SecurePagesConfiguration.Urls.AddRegex(@"(.*)account", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);
1
Paul

Sur mon environnement de développement, j'aime avoir un répertoire de publication séparé avec IIS installé avec un certificat auto signé, qui est différent de mon répertoire de code sans un certificat que je débogue directement à l'intérieur de Visual Studio. Dans ce scénario !Request.IsLocal n'est pas idéal car il ne fonctionne nulle part sur votre environnement de développement, même dans le répertoire IIS avec le certificat. Je préfère ceci:

if (!IsPostBack && !HttpContext.Current.IsDebuggingEnabled) 
{
    // do http->https and https->http redirection here
}

HttpContext.Current.IsDebuggingEnabled est basé sur la valeur de compilation debug = "true/false" dans votre web.config. Je l'ai défini sur true dans mon répertoire de code et sur false dans mon répertoire de publication lorsque j'ai besoin de tester la redirection http et https localement.

J'ajoute le IsPostBack simplement pour le rendre (légèrement) plus efficace en sautant la vérification ssl supplémentaire lorsqu'elle n'est pas nécessaire.

1
TTT