После исследования aroud я смог решить эту проблему с помощью IIS Express и переопределения метода OnAuthorization класса Controller (ссылка № 1). Я также пошел по маршруту, рекомендованному Гансельманом (ссылка № 2). Однако я не был полностью удовлетворен этими двумя решениями по двум причинам:
1. Ссылка # 1 OnAuthorization работает только на уровне действия, а не на уровне класса контроллера
2. Ссылка № 2 требует большого количества настроек (Win7 SDK для makecert), команд netsh и, чтобы использовать порт 80 и порт 443, мне нужно запустить VS2010 в качестве администратора, на что я нахмурился.
Итак, я придумал это решение, которое фокусируется на простоте со следующими условиями:
Я хочу иметь возможность использовать attbbute RequireHttps на уровне контроллера или уровне действия
Я хочу, чтобы MVC использовал HTTPS при наличии атрибута RequireHttps и HTTP, если он отсутствует
Я не хочу запускать Visual Studio от имени администратора
Я хочу использовать любые порты HTTP и HTTPS, которые назначены IIS Express (см. Примечание № 1)
Я могу повторно использовать самозаверяющий сертификат SSL IIS Express, и мне все равно, если я увижу недопустимое приглашение SSL
Я хочу, чтобы dev, test и production имели одинаковую кодовую базу и тот же двоичный файл и были независимы от дополнительных настроек (например, используя netsh, mmc-оснастку cert и т. Д.), Насколько это возможно
Теперь, с учетом фона и объяснений, я надеюсь, что этот код поможет кому-то и сэкономит время. По сути, создайте класс BaseController, который наследуется от Controller, и выведите классы контроллера из этого базового класса. Поскольку вы читали это далеко, я предполагаю, что вы знаете, как это сделать. Итак, счастливого кодирования!
Примечание # 1: Это достигается с помощью полезной функции 'getConfig' (см. Код)
Ссылка № 1: http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
Ссылка № 2: http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx
========== Код в BaseController ===================
#region Override to reroute to non-SSL port if controller action does not have RequireHttps attribute to save on CPU
// By L. Keng, 2012/08/27
// Note that this code works with RequireHttps at the controller class or action level.
// Credit: Various stackoverflow.com posts and http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
protected override void OnAuthorization(AuthorizationContext filterContext)
{
// if the controller class or the action has RequireHttps attribute
var requireHttps = (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Count() > 0
|| filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Count() > 0);
if (Request.IsSecureConnection)
{
// If request has a secure connection but we don't need SSL, and we are not on a child action
if (!requireHttps && !filterContext.IsChildAction)
{
var uriBuilder = new UriBuilder(Request.Url)
{
Scheme = "http",
Port = int.Parse(getConfig("HttpPort", "80")) // grab from config; default to port 80
};
filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
}
}
else
{
// If request does not have a secure connection but we need SSL, and we are not on a child action
if (requireHttps && !filterContext.IsChildAction)
{
var uriBuilder = new UriBuilder(Request.Url)
{
Scheme = "https",
Port = int.Parse(getConfig("HttpsPort", "443")) // grab from config; default to port 443
};
filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
}
}
base.OnAuthorization(filterContext);
}
#endregion
// a useful helper function to get appSettings value; allow caller to specify a default value if one cannot be found
internal static string getConfig(string name, string defaultValue = null)
{
var val = System.Configuration.ConfigurationManager.AppSettings[name];
return (val == null ? defaultValue : val);
}
============== код конца ================
В Web.Release.Config добавьте следующее, чтобы очистить HttpPort и HttpsPort (чтобы использовать значения по умолчанию 80 и 443).
<appSettings>
<add key="HttpPort" value="" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
<add key="HttpsPort" value="" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
</appSettings>