2010-01-19 26 views
6

Sto utilizzando Request.IsSecureConnection per verificare la presenza di SSL e il reindirizzamento, se appropriato. Quando si esegue il mio sito Web asp.net sul cloud di Rackspace, il server è in esecuzione dietro un cluster SSL, pertanto IsSecureConnection restituirà sempre false. Lo stesso vale per verificare se l'url contiene "https: //", sempre falso, controlla la porta, ecc. Quindi il sito web rimane bloccato in un grosso ciclo di reindirizzamento.Verificare SSL quando è ospitato nel cloud Rackspace (Mosso)

C'è un altro modo per controllare SSL e reindirizzare dove appropriato? Qualcuno che ha effettivamente fatto questo sul cloud di Rackspace?

Public Class SecurityAwarePage 
    Inherits Page 

    Private _requireSSL As Boolean = False 

    Public Property RequireSSL() As Boolean 
     Get 
      Return _requireSSL 
     End Get 
     Set(ByVal value As Boolean) 
      _requireSSL = value 
     End Set 
    End Property 

    Private ReadOnly Property IsSecure() As Boolean 
     Get 
      Return Request.IsSecureConnection 
     End Get 
    End Property 

    Protected Overrides Sub OnInit(ByVal e As System.EventArgs) 
     MyBase.OnInit(e) 

     PushSSL() 
    End Sub 

    Private Sub PushSSL() 
     Const SECURE As String = "https://" 
     Const UNSECURE As String = "http://" 

     If RequireSSL AndAlso Not IsSecure Then 
      Response.Redirect(Request.Url.ToString.Replace(UNSECURE, SECURE)) 
     ElseIf Not RequireSSL AndAlso IsSecure Then 
      Response.Redirect(Request.Url.ToString.Replace(SECURE, UNSECURE)) 
     End If 

    End Sub 

End Class 
+0

Non che abbia qualcosa a che fare con la domanda, ma tu hai il mio apprezzamento di usare const per stringhe anche semplici come "http" e "https". –

risposta

5

Anche se è difficile verificare se SSL è occupato, il problema consiste nel forzare SSL.

Dal RackspaceCloud Support knowledge base:

È possibile URL nel web.config riscrivere:

<configuration> 
<system.webServer> 
    <rewrite> 
    <rules> 
     <rule name="Redirect to HTTPS" stopProcessing="true"> 
     <match url=".*" /> 
     <conditions> 
      <add input="{HTTP_CLUSTER_HTTPS}" pattern="^on$" negate="true" /> 
      <add input="{HTTP_CLUSTER-HTTPS}" pattern=".+" negate="true" /> 
     </conditions> 
     <action type="Redirect" url="https://{HTTP_HOST}{SCRIPT_NAME}" redirectType="SeeOther" /> 
     </rule> 
    </rules> 
    </rewrite> 
</system.webServer> 
</configuration> 

È possibile forzare SSL in ASP.NET:

<%@ Page Language="C#" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 

<script runat="server"> 
    protected void Page_Load(object sender, System.EventArgs e) 
    { 
    if(Request.ServerVariables["HTTP_CLUSTER_HTTPS"] != "on") 
    { 
     if(Request.ServerVariables.Get("HTTP_CLUSTER-HTTPS") == null) 
     { 
     string xredir__, xqstr__; 

     xredir__ = "https://" + Request.ServerVariables["SERVER_NAME"]; 
     xredir__ += Request.ServerVariables["SCRIPT_NAME"]; 
     xqstr__ = Request.ServerVariables["QUERY_STRING"]; 

     if (xqstr__ != "") 
      xredir__ = xredir__ + "?" + xqstr__; 

     Response.Redirect(xredir__); 
     } 
    } 
    Response.Write("SSL Only"); 
    } 
</script> 

<html> 
<head id="Head1" runat="server"> 
    <title>SSL Only</title> 
</head> 
<body> 
</body> 
</html> 
+0

Grazie, ho cercato i file della guida e non l'ho trovato da solo. Guardando indietro, suppongo che sarebbe stato bello fare il ciclo della raccolta ServerVariables e vedere cosa c'era. –

+0

Sono curioso, è un errore di "HTTP_CLUSTER-HTTPS"? Ne hai uno con due underscore e uno con un trattino basso e un trattino. –

+0

Le regole di riscrittura [link] (http://learn.iis.net/page.aspx/465/url-rewrite-module-configuration-reference/#Rule_action) sostituiscono trattini con caratteri di sottolineatura, quindi probabilmente non ha importanza. Sembra funzionare esattamente come mostrato qui o con entrambi i underscore della mia esperienza diretta. – philw

5

mi sono imbattuto in questo lo stesso problema con Rackspace Cloud e ha finito per risolverlo implementando manualmente un metodo di estensione Request.IsSecureConnection() e sostituendo il framework RequireHttpsAttribute con il mio. Spero che qualcun altro possa trovare utile anche questo.

/// <summary> 
/// Replaces framework-provided RequireHttpsAttribute to disable SSL requirement for local requests 
/// and properly enforce SSL requirement when used with Rackspace Cloud's load balancer 
/// </summary> 
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] 
public class RequireHttpsAttribute : FilterAttribute, IAuthorizationFilter 
{ 
    public virtual void OnAuthorization(AuthorizationContext filterContext) { 
     if (filterContext == null) { 
      throw new ArgumentNullException("filterContext"); 
     } 

     if (filterContext.HttpContext.Request.IsLocal) 
      return; 

     if (!filterContext.HttpContext.Request.IsSecureConnection()) { 
      HandleNonHttpsRequest(filterContext); 
     } 
    } 

    protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext) { 
     // only redirect for GET requests, otherwise the browser might not propagate the verb and request 
     // body correctly. 

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

     // redirect to HTTPS version of page 
     string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl; 
     filterContext.Result = new RedirectResult(url); 
    } 

} 

public static class Extensions { 
    /// <summary> 
    /// Gets a value which indicates whether the HTTP connection uses secure sockets (HTTPS protocol). Works with Rackspace Cloud's load balancer 
    /// </summary> 
    /// <param name="request"></param> 
    /// <returns></returns> 
    public static bool IsSecureConnection(this HttpRequestBase request) { 
     const string rackspaceSslVar = "HTTP_CLUSTER_HTTPS"; 

     return (request.IsSecureConnection || (request.ServerVariables[rackspaceSslVar] != null || request.ServerVariables[rackspaceSslVar] == "on")); 
    } 

    /// <summary> 
    /// Gets a value which indicates whether the HTTP connection uses secure sockets (HTTPS protocol). Works with Rackspace Cloud's load balancer 
    /// </summary> 
    /// <param name="request"></param> 
    /// <returns></returns> 
    public static bool IsSecureConnection(this HttpRequest request) { 
     const string rackspaceSslVar = "HTTP_CLUSTER_HTTPS"; 

     return (request.IsSecureConnection || (request.ServerVariables[rackspaceSslVar] != null || request.ServerVariables[rackspaceSslVar] == "on")); 
    } 
} 
+0

quindi perché è necessario implementare una sostituzione per RequireHttpsAttribute class? – Corgalore

+0

@Corgalore Bene, perché non posso semplicemente sostituire HttpRequest.IsSecureConnection (una proprietà), che è ciò che il RequireHttpsAttribute incorporato sta controllando. Ho creato un'estensione * su HttpRequest chiamata IsSecureConnection() (un metodo). Pertanto, il mio sostituto RequireHttpAttribute controlla invece la mia estensione. –

Problemi correlati