我有一个MVC 4 Web应用程序,我需要SSL来处理一组特定的操作,现在我也希望登录过程受SSL保护。
设置完所有后,会发生的情况是,由于Login页面的redirectToUrl参数未指定架构,因此无论我设置的[RequireHttps]
属性如何,所有需要登录的页面都会被重定向到https(或最好在动作上说不设置。
由于我没有使用RequireHttps属性装饰的页面主持混合内容,这会触发通常的浏览器警告,这会让用户感到困惑,我想避免。
有没有办法解决这个问题?我想从登录操作中获取模式,但除了returnUrl参数之外,我找不到对原始请求的引用,这只是一个相对路径。
我在SO中找到的引用是creating a custom attribute来装饰每个不需要https的Action,但是还有什么比这更干?
答案 0 :(得分:2)
我发现以下内容很有用,而不是用[RequireHttps]进行装饰我用[Secure]装饰,然后这个属性为我工作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MyNameSpace.Attributes
{
public class SecureAttribute : ActionFilterAttribute
{
#region Variables and Properties
public bool PermanentRedirect { get; set; }
#endregion
#region Public Methods
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Cache for efficiency
var request = filterContext.HttpContext.Request;
var response = filterContext.HttpContext.Response;
// Make sure we're not in https or local
if (!request.IsSecureConnection)
{
string redirectUrl = request.Url.ToString().Replace(
Uri.UriSchemeHttp,
Uri.UriSchemeHttps);
if (PermanentRedirect)
{
// Set the status code and text description to redirect permanently
response.StatusCode = 301;
response.StatusDescription = "Moved Permanently";
}
else
{
// Set the status code and text description to redirect temporary (found)
response.StatusCode = 302;
response.StatusDescription = "Found";
}
// Add the location header to do the redirect
response.AddHeader("Location", redirectUrl);
}
base.OnActionExecuting(filterContext);
}
#endregion
}
}
答案 1 :(得分:2)
那么, 我最后选择了我原来帖子中评论中描述的解决方案,这证明是最无痛的方法。
总结一下(所有归功于 Luke Sampsons 的代码,我只是在这里重新发布以供快速参考)这基本上是代码:
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);
}
}
public class RetainHttpsAttribute:FilterAttribute{}
ExitHttpsIfNotRequired
属性可用于修饰用于派生Web应用程序中所有控制器的基本控制器类。