我有以下属性以确保远程站点页面以https模式打开。
public class RemoteRequireHttpsAttribute : RequireHttpsAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentException("Filter Context");
}
if (filterContext != null && filterContext.HttpContext != null)
{
if (filterContext.HttpContext.Request.IsLocal)
{
return;
}
else
{
string val = ConfigurationManager.AppSettings["RequireSSL"].Trim();
bool requireSsl = bool.Parse(val);
if (!requireSsl)
{
return;
}
}
}
base.OnAuthorization(filterContext);
}
}
本地开发现在正常工作,因为我不希望它以https模式打开。
开发站点以https模式打开页面 - 此处没有问题(单个节点)。
我正在设置的生产(负载平衡 - 2个节点)站点在哪里给我跟随错误。请注意,dev和prod站点具有相同的setings和web.config
页面未正确重定向
Firefox检测到服务器正在以永远无法完成的方式重定向此地址的请求。
有时可能会因禁用或拒绝接受Cookie而导致此问题。
开发网站网址就像 http://dev.datalab.something.org
Prod网站的网址就像 http://datalab.something.org
这是电话
[RemoteRequireHttps]
public ActionResult Index(string returnUrl, string error)
我在这里缺少什么?
更新1:我的管理员已确认已在lad balancer evel设置了SSL终止。我查看了iis站点设置,但我没有看到https绑定。我只看到http绑定。他是否还需要设置https绑定?
更新2: @AlexeiLevenkov向我指出了正确的方向,this post有我使用的代码,它正在运行。将代码移动到单独的答案中。
答案 0 :(得分:2)
您的站点是支持SSL终止的负载均衡器 - 因此,无论用户看到什么,所有到您站点的传入流量都是HTTP。这会导致您的代码始终尝试重定向到HTTPS版本,从而无限循环。
要修复的选项:
x-forwarded-for
是用于此目的的常见内容。如果使用这些标头或需要一些其他配置,您可能需要与网络管理员核实如何调查此类问题:
答案 1 :(得分:1)
并不是说我反对编写好的自定义属性,或许在web.config中执行重定向并使用web.config可用的转换将生产部署中的启用值从false更改为true是没有意义的?
<rewrite>
<rules>
<rule name="SSL_ENABLED" enabled="false" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
答案 2 :(得分:1)
如@AlexeiLevenkov所述,将修复程序移到单独的答案中。
public class RemoteRequireHttpsAttribute : RequireHttpsAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentException("Filter Context");
}
if(filterContext.HttpContext != null)
{
if (filterContext.HttpContext.Request.IsSecureConnection)
{
return;
}
var currentUrl = filterContext.HttpContext.Request.Url;
if (currentUrl.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.CurrentCultureIgnoreCase))
{
return;
}
if (string.Equals(filterContext.HttpContext.Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase))
{
return;
}
if (filterContext.HttpContext.Request.IsLocal)
{
return;
}
var val = ConfigurationManager.AppSettings["RequireSSL"].Trim();
var requireSsl = bool.Parse(val);
if (!requireSsl)
{
return;
}
}
base.OnAuthorization(filterContext);
}
}
我也更新了ExitHttps属性。这也有类似的问题......
public class ExitHttpsAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentException("Filter Context");
}
if (filterContext.HttpContext == null)
{
return;
}
var isSecure = filterContext.HttpContext.Request.IsSecureConnection;
var currentUrl = filterContext.HttpContext.Request.Url;
if (!isSecure && currentUrl.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.CurrentCultureIgnoreCase))
{
isSecure = true;
}
if (!isSecure && string.Equals(filterContext.HttpContext.Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase))
{
isSecure = true;
}
if (isSecure)
{
//in these cases keep https
// abort if a [RequireHttps] attribute is applied to controller or action
if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0)
{
isSecure = false;
}
if (isSecure && filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0)
{
isSecure = false;
}
// abort if a [RetainHttps] attribute is applied to controller or action
if (isSecure && filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (RetainHttpsAttribute), true).Length > 0)
{
isSecure = false;
}
if (isSecure && filterContext.ActionDescriptor.GetCustomAttributes(typeof (RetainHttpsAttribute), true).Length > 0)
{
isSecure = false;
}
// abort if it's not a GET request - we don't want to be redirecting on a form post
if (isSecure && !String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
isSecure = false;
}
}
if (!isSecure)
{
return;
}
// redirect to HTTP
var url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult(url);
}
}