Redirect loop with SSL action filter in ASP.NET MVC
I am using an ActionFilter (see below) to detect whe开发者_高级运维ther or not 1. the current controller/action requires SSL and 2. SSL is currently being used, and redirect accordingly.
This works fine locally (using a dummy cert in IIS 7) but once I get it up on the server I get an error indicating an infinite redirect loop.
Any ideas?
public class SslFilter : ActionFilterAttribute
{
public SslFilter(bool sslRequired)
{
SslRequired = sslRequired;
}
public bool SslRequired { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpRequestBase req = filterContext.HttpContext.Request;
HttpResponseBase res = filterContext.HttpContext.Response;
var builder = new UriBuilder(req.Url);
if (SslRequired && !req.IsSecureConnection)
{
builder.Scheme = Uri.UriSchemeHttps;
builder.Port = 443;
res.Redirect(builder.Uri.ToString());
}
else if (!SslRequired && req.IsSecureConnection)
{
builder.Scheme = Uri.UriSchemeHttp;
builder.Port = 80;
res.Redirect(builder.Uri.ToString());
}
base.OnActionExecuting(filterContext);
}
}
Firefox error:
The page isn't redirecting properly
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
This problem can sometimes be caused by disabling or refusing to accept cookies.
Try redirecting in a more MVCish way:
var builder = new UriBuilder(req.Url);
if (SslRequired && !req.IsSecureConnection)
{
builder.Scheme = Uri.UriSchemeHttps;
builder.Port = 443;
filterContext.Result = new RedirectResult(builder.Uri.ToString());
filterContext.Cancel = true;
}
else if (!SslRequired && req.IsSecureConnection)
{
builder.Scheme = Uri.UriSchemeHttp;
builder.Port = 80;
filterContext.Result = new RedirectResult(builder.Uri.ToString());
filterContext.Cancel = true;
}
else
{
base.OnActionExecuting(filterContext);
}
I had this same issue on a site that I'm building and found that for some reason it had to do with having the port number in the url. So, builder.Uri.ToString() was outputting http://domain.com:80/ or https://domain.com:443/, which as far as I am aware should be fine, but we switched to use builder.Uri.AbsoluteUri and it fixed the issue. Here is a sample of our code...
UriBuilder __urlBuilder = new UriBuilder(__context.Request.Url);
if (!HttpContext.Current.Request.Url.Scheme.Contains("https")) {
if (this.Required == RequiredStates.Required) {
__urlBuilder.Scheme = "https";
__urlBuilder.Port = 443;
HttpContext.Current.Response.Redirect(__urlBuilder.Uri.AbsoluteUri, true);
}
}
else {
if (this.Required == RequiredStates.NotRequired) {
__urlBuilder.Scheme = "http";
__urlBuilder.Port = 80;
HttpContext.Current.Response.Redirect(__urlBuilder.Uri.AbsoluteUri, true);
}
}
Please check certificate installed on the server. Use the SSL configuration tool from MS to detect the issue. Most probably the private is missing.
精彩评论