我遇到了与Rackspace Cloud同样的问题,最后通过手动实现Request.IsSecureConnection()扩展方法并用我自己的方法替换框架的RequireHttpsAttribute来解决它。希望其他人也会觉得这很有用。
/// <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")); } }
虽然很难检查SSL是否参与解决问题的方法是强制使用SSL。
来自 RackspaceCloud支持知识库 :
您可以在web.config中重写URL:
<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>
您可以在ASP.NET中强制使用SSL:
<%@ 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>