asp.net c # reindirizzamento da http a https

Quindi nel mio codice voglio rilevare se la mia pagina di accesso viene chiamata http e redirect a https.

So che non ci sono modi in codice per scuoiare questo gatto, ma per ragioni tecniche frustranti sono indotto a farlo in codice.

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

Quindi lo scarico nel mio Page_Load(...) , assicurandomi che il mio debugger utilizzi IIS reale, non IIS VS2008 e colpisca il debug.

Nel debugger, waltz along, premi Response.Redirect (” https: //localhost/StudentPortal3G/AccessControl/AdLogin.aspx “), premi f5.

Ottieni “Internet Explorer non può visualizzare la pagina Web, URL è HTTP, non HTTPS. Non riceve un errore informativo … la stessa cosa non accade nel debugger.

Quindi cosa mi sto perdendo? non sembra essere una scienza missilistica, ho visto un codice simile su molti blog …

Che cosa sto facendo di sbagliato? Immagino che debba essere un errore Rookie assolutamente ovvio, ma non lo vedo.

!Request.IsLocal anche un !Request.IsLocal per assicurarmi che non stia eseguendo il debug, anche se stai usando una vera istanza di IIS con un cert applicato durante il debug che non dovrebbe essere un problema.

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

Nota: questa risposta presuppone un contesto MVC all’interno di un controller in cui HttpContext è una proprietà che mantiene il contesto corrente. Se sei abbastanza sfortunato da continuare a utilizzare WebForms o stai facendo riferimento al contesto in modo degenerato, dovrai utilizzare HttpContext.Current.ApplicationInstance.CompleteRequest() .

Nota: l’ho aggiornato per essere coerente con il modello consigliato per terminare la richiesta in base alla documentazione del framework .

Quando si utilizza questo metodo in un gestore di pagine per terminare una richiesta per una pagina e avviare una nuova richiesta per un’altra pagina, impostare endResponse su false e quindi chiamare il metodo CompleteRequest. Se si specifica true per il parametro endResponse, questo metodo chiama il metodo End per la richiesta originale, che genera un’eccezione ThreadAbortException al termine. Questa eccezione ha un effetto dannoso sulle prestazioni dell’applicazione Web, motivo per cui è consigliabile passare false per il parametro endResponse. Per ulteriori informazioni, consultare il metodo End.

Io di solito chiamo il seguente da OnPreInit in una class base da cui ereditano tutte le mie pagine. Certo, potresti farlo in ogni pagina … ma non vorresti farlo ora?

Nota che ho due proprietà per ogni pagina in modo da poter specificare il requisito SSL per ogni pagina (RequiresSSL) mentre posso anche eseguire l’override e il reindirizzamento, se lo voglio (con IgnoreRequiresSSL, che è utile per pagine come le pagine di errore che riscrivere e non sapere se saranno crittografati o meno), ma ovviamente è ansible rimuoverli per configurazioni semplici.

  protected override void OnPreInit(EventArgs e) { base.OnPreInit(e); if (!IsPostBack) RedirectAccordingToRequiresSSL(); ... } ///  /// Redirect if necessary to ssl or non-ssl enabled URL dependant on RequiresSSL property setting. ///  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 } ///  /// Redirect as requested to specified scheme ///  ///  private void RedirectAccordingToRequiresSSL(string scheme) { var url = scheme + Uri.SchemeDelimiter + Request.Url.Authority + Request.Url.PathAndQuery; Response.Redirect(url, false); } 

Secondo me il seguente è il miglior approccio a tutto tondo.

Tre ragioni

  1. Funziona sia per MVC che Web API come avviene a livello di IIS .
  2. Non ha effetto sulle impostazioni locali / di debug. (Il reindirizzamento permanente può rovinarti quando esegui il debug di siti non https sul tuo pc).
  3. Utilizza un reindirizzamento permanente, quindi tutte le richieste future passeranno automaticamente a https

Aggiungi semplicemente quanto segue alla tua sezione in “Web.config” per il tuo progetto.

   ....                       

Puoi anche usare il nuovo 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); } 

Vorrei anche suggerire la soluzione di tvalfonsso, ma con una piccola modifica nel caso in cui tu abbia qualche riscrittura di URL (RawUrl differisce da 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); } 

Uno dei modi in cui sono stato in grado di applicare un reindirizzamento https è il seguente:

Nel pool di app ho la mia applicazione in esecuzione solo sulla porta 443, quindi non è ansible che si verifichi una sessione non crittografata (a meno che lo schema di crittografia non sia interrotto da una vulnerabilità ..). Ho creato un’altra applicazione sulla porta 80 con lo stesso indirizzo IP che contiene solo un file web.config con il seguente codice

      

disclaimer – Sono stato coinvolto nello sviluppo di questo progetto

Raccomanderei l’uso di http://nuget.org/packages/SecurePages/. Ti dà la possibilità di proteggere pagine specifiche o utilizzare Regex per definire le corrispondenze. Forzerà anche tutte le pagine che non corrispondono al Regex o direttamente specificate su HTTP.

Puoi installarlo tramite NuGet: Install-Package SecurePages

I documenti sono qui: https://github.com/webadvanced/Secure-Page-manager-for-asp.net#secure-pages

Uso semplice:

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

o

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

Ecco la mia soluzione:

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

Dove Settings.CanonicalDomain è il tuo nome host HTTPS. Reindirizzamenti 301 che potrebbero essere la risposta corretta in alcuni casi.

Nel mio ambiente di sviluppo, mi piace avere una directory di pubblicazione separata con IIS installato con un certificato autofirmato, che è diverso dalla mia directory di codice senza un certificato che eseguo il debug direttamente all’interno di Visual Studio. In questo scenario !Request.IsLocal non è l’ideale perché non funziona in nessun punto del tuo ambiente di sviluppo, nemmeno nella directory IIS con il certificato. Preferisco questo:

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

HttpContext.Current.IsDebuggingEnabled si basa sul valore di compilation debug = “true / false” nel web.config. Ho impostato su true nella mia directory di codice e false nella mia directory di pubblicazione quando ho bisogno di testare il reindirizzamento http e https localmente.

Aggiungo in IsPostBack semplicemente per renderlo (leggermente) più efficiente saltando il controllo ssl extra quando non è necessario.