Почему, если SSL включен с [RequireHttps] на уровне действия, он остается включенным навсегда?
Мы хотим использовать https только тогда, когда это строго необходимо. Почему после вызова действия, как показано ниже, оно остается включенным навсегда?
[RequireHttps]
public ActionResult LogIn()
{
if(Request.IsAuthenticated)
return RedirectToAction("Index", "Account");
return View();
}
Что мы можем сделать, чтобы отключить его, когда он не нужен?
Благодарю.
2 ответа
Я использую этот фильтр действий, который перенаправляет обратно на http, когда действие https завершено:
using System.Web.Mvc;
using System;
public class ExitHttpsIfNotRequiredAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
// abort if it's not a secure connection
if (!filterContext.HttpContext.Request.IsSecureConnection) return;
// abort if a [RequireHttps] attribute is applied to controller or action
if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0) return;
if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0) return;
// abort if a [RetainHttps] attribute is applied to controller or action
if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RetainHttpsAttribute), true).Length > 0) return;
if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(RetainHttpsAttribute), true).Length > 0) return;
// abort if it's not a GET request - we don't want to be redirecting on a form post
if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) return;
// redirect to HTTP
string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult(url);
}
}
Атрибут [RequireHttps] может использоваться в типе контроллера или методе действия, чтобы сказать "к нему можно получить доступ только через SSL". Не-SSL запросы к контроллеру или действию будут перенаправлены на версию SSL (если HTTP GET) или отклонены (если HTTP POST). Вы можете переопределить RequireHttpsAttribute и изменить это поведение, если хотите. Нет встроенного атрибута [RequireHttp], который делает обратное, но вы можете легко создать свой собственный, если хотите.
Есть также перегрузки Html.ActionLink(), которые принимают параметр протокола; вы можете явно указать "http" или "https" в качестве протокола. Вот документация MSDN об одной такой перегрузке. Если вы не указываете протокол или вызываете перегрузку, у которой нет параметра протокола, предполагается, что вы хотите, чтобы ссылка имела тот же протокол, что и текущий запрос.
Причина, по которой у нас нет атрибута [RequireHttp] в MVC, заключается в том, что в этом нет особой выгоды. Это не так интересно, как [RequireHttps], и это побуждает пользователей поступать неправильно. Например, многие веб-сайты входят в систему через SSL и перенаправляют обратно на HTTP после входа в систему, что абсолютно неправильно. Ваш файл cookie для входа в систему так же секретен, как и ваше имя пользователя + пароль, и теперь вы отправляете его открытым текстом по сети. Кроме того, вы уже нашли время, чтобы выполнить квитирование и защитить канал (что является основной причиной того, что HTTPS медленнее, чем HTTP) перед запуском конвейера MVC, поэтому [RequireHttp] не будет выполнять текущий запрос или будущее запросы гораздо быстрее.
Если вы используете utube, измените встраивание на использование HTTPS, а не HTTP. Если вы переходите на HTTP с HTTPS без правильного выхода (см. http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.signout.aspx) ваше имя пользователя + пароль широко открыты. Недостаточно позвонить в SignOut.