2012-05-27 35 views
3

我有一個MVC 4 Web應用程序,我要求SSL針對特定的一組操作,現在我希望登錄過程也受SSL保護。如何激活僅用於登錄和特定頁面的SSL MVC

設置完所有事情後,會發生什麼,因爲登錄頁面的redirectToUrl參數沒有指定模式,所有需要登錄的頁面都會被重定向到https,而不管我設置的[RequireHttps]屬性(或更好地說不是設置)上的行動。

由於我沒有用RequireHttps屬性主機混合內容來裝飾的頁面,這觸發了通常的瀏覽器警告,這對用戶來說是令人困惑的,我想避免。

有沒有辦法解決這個問題?我想從登錄操作中獲取模式,但除了返回相對路徑的returnUrl參數外,我找不到原始請求的引用。

我在SO中找到的參考是creating a custom attribute來裝飾每個不需要HTTPS的操作,但還有什麼比這更幹?

+0

好吧,爲了避免重複一個HttpsNotRequired屬性,我可以用它來裝飾一個基礎控制器,但仍然在想是否有更好的解決方案。 – eddo

回答

2

好吧,我 最終選擇在評論我原來的職位,這證明是最無痛的方式描述的解決方案。

只是爲了總結(所有信貸盧克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應用程序中的所有控制器。

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 
    } 
} 
+0

那麼,我認爲我應該使用此屬性來裝飾登錄操作。不幸的是,它似乎沒有幫助 - 登錄後頁面仍然重定向到https。不知道我是否按照你的意圖使用它,以防止它澄清.. – eddo

+0

您可能需要一個模塊來檢測用戶是否已登錄。如果這樣使它們保持在https中,則將它們重定向到http。如果用戶已經登錄,我想讓他們保存在https中以保護未來的請求? 或者你想在登錄完成後將所有內容重定向到http? –