如何激活SSL仅用于登录和特定页面MVC

时间:2012-05-27 09:23:24

标签: asp.net-mvc asp.net-mvc-4 ssl https forms-authentication

我有一个MVC 4 Web应用程序,我需要SSL来处理一组特定的操作,现在我也希望登录过程受SSL保护。

设置完所有后,会发生的情况是,由于Login页面的redirectToUrl参数未指定架构,因此无论我设置的[RequireHttps]属性如何,所有需要登录的页面都会被重定向到https(或最好在动作上说设置。

由于我没有使用RequireHttps属性装饰的页面主持混合内容,这会触发通常的浏览器警告,这会让用户感到困惑,我想避免。

有没有办法解决这个问题?我想从登录操作中获取模式,但除了returnUrl参数之外,我找不到对原始请求的引用,这只是一个相对路径。

我在SO中找到的引用是creating a custom attribute来装饰每个不需要https的Action,但是还有什么比这更干?

2 个答案:

答案 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应用程序中所有控制器的基本控制器类。