2011-08-18 13 views
8

में RequHttps विशेषता के साथ एक अलग बंदरगाह निर्दिष्ट करने के लिए मैं केवल एएसपी.नेट एमवीसी सीख रहा हूं, और मैंने हाल ही में एसएसएल का उपयोग करने के लिए जीईटी अनुरोध को रीडायरेक्ट करने के लिए [RequHttps] विशेषता पाई है, जैसे ...एमवीसी 3

[RequireHttps] //apply to all actions in controller 
public class SomeController 
{ 
    [RequireHttps] //apply to this action only 
    public ActionResult SomeAction() 
    { 
     ... 
    } 
} 

जब विकास सर्वर के रूप में आईआईएस एक्सप्रेस का उपयोग कर, यह सफलतापूर्वक http://localhost:55945/... से https://localhost/... करने के लिए अनुरोध पुनर्निर्देश।

हालांकि मेरे विकास प्रणाली पर, मेरी परियोजना पोर्ट 44300 पर एचटीटीपीएस का उपयोग कर रही है (यह विजुअल स्टूडियो 2010 द्वारा स्वचालित रूप से कॉन्फ़िगर किया गया था), और मुझे अभी तक एमवीसी को पुनर्निर्देशन में उस पोर्ट नंबर का उपयोग करने के लिए कोई रास्ता नहीं मिला है, इसलिए कि यह इसके बजाय आवश्यक https://localhost:43300/... पर जाता है।

मुझे वास्तव में यह स्वचालित होने की उम्मीद है, एसएसएल पोर्ट नंबर स्वचालित रूप से विजुअल स्टूडियो द्वारा सेट किया गया था, और जहां तक ​​मैं कह सकता हूं, यह एमवीसी 3 में [RequHttps] विशेषता का उपयोग कर सभी डेवलपर्स को प्रभावित करेगा। समाधान के लिए मेरी खोज में, मैंने कुछ पैची "चारों ओर काम" समाधान देखा है, लेकिन ऐसा कुछ भी नहीं है जो इसे ठीक करने के लिए निश्चित रूप से "सही तरीका" प्रतीत होता है।

तो चीजें "सही तरीके से" कर रही हैं, मैं एमवीसी 3 में [RequHttps] विशेषता को बताने के लिए एमवीसी 3 में [RequHttps] विशेषता को बताने के लिए क्या बदलूं (मेरा प्रोजेक्ट कॉन्फ़िगरेशन में) जो मेरी परियोजना को कॉन्फ़िगर किया गया है उपयोग कर रहे हैं?

या वैकल्पिक रूप से, क्या एमवीसी 3 प्रोजेक्ट में एसएसएल समर्थन स्थापित करने के लिए कुछ अन्य पूरी तरह से अलग और बेहतर "सही तरीका" है, जिसमें यह समस्या नहीं है?

उत्तर

12

RequHttpsAttribute काफी सरल है और इसे किसी विशिष्ट पोर्ट पर रीडायरेक्ट करने के लिए parametrized नहीं किया जा सकता है। यदि आपको वास्तव में इसकी आवश्यकता है तो आप एक उप-वर्ग बना सकते हैं और रीडायरेक्ट यूआरएल को अलग-अलग लिखने के लिए HandleNonHttpsRequest विधि को ओवरराइड कर सकते हैं।

protected override void HandleNonHttpsRequest(AuthorizationContext filterContext) { 
    base.HandleNonHttpsRequest(filterContext); 

    // redirect to HTTPS version of page 
    string url = "https://" + filterContext.HttpContext.Request.Url.Host + ":" + MyConfig.SslPort + filterContext.HttpContext.Request.RawUrl; 
    filterContext.Result = new RedirectResult(url); 
} 

हालांकि, अगर अपने पूरे साइट HTTPS के साथ चलाता है तुम सिर्फ वी.एस. में वेब परियोजना संपत्तियों में कॉन्फ़िगर कर सकता है (-> प्रारंभ कार्रवाई - वेब> URL शुरू) अपने पोर्ट के साथ सही HTTPS यूआरएल को खोलने के लिए और नहीं का उपयोग स्थानीय परीक्षण के लिए पुनर्निर्देशन सुविधा।

+0

मुझे आपके जवाब का पहला हिस्सा मिलता है, भले ही यह एक हैक जैसा प्रतीत होता है, जिसके लिए हैक करने की आवश्यकता नहीं है। लेकिन मैं आपके अंतिम पैराग्राफ को समझ नहीं पा रहा हूं। मुझे अपनी विकास प्रणाली को व्यवहार करने की आवश्यकता है (व्यावहारिक रूप से व्यावहारिक) उसी तरह से उपयोगकर्ता सिस्टम व्यवहार करेगा। इसका मतलब है कि कुछ पेज HTTPS का उपयोग करेंगे, और कुछ नहीं करेंगे। इसका यह भी अर्थ है कि मैं यह नियंत्रित नहीं कर सकता कि उपयोगकर्ता किस यूआरएल के साथ साइट दर्ज करेगा। –

+0

मेरा मतलब यह था कि आपको शायद अपने देव मशीन पर काम करने के लिए वास्तविक रीडायरेक्ट की आवश्यकता नहीं है, और उत्पादन में यह मानक HTTPS पोर्ट होगा। यह मामला होगा यदि पूरी साइट HTTPS के तहत चलती है, क्योंकि आप केवल सही HTTPS पोर्ट के साथ ऐप शुरू कर सकते हैं और HTTPS संदर्भ में रह सकते हैं। अगर मैं अच्छी तरह से समझता हूं तो यह मामला नहीं है, इसलिए आपको रीडायरेक्ट को अपनी देव मशीन पर भी काम करने की ज़रूरत है। मैं जवाब अद्यतन करता हूं और वाक्यांश का बेहतर प्रयास करता हूं जो मेरा मतलब था, लेकिन यह आपके लिए प्रासंगिक नहीं हो सकता है। –

0

मुझे काफी परेशान है कि मुझे यह अधिकार प्राप्त करने के लिए घंटों खर्च क्यों करना पड़ा। मैं एक यूआरएल रास्ता स्कॉट Hanselman इसे यहाँ बताते हैं के लिए इसी तरह के पुनर्लेखन की थी:

http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.asp एक्स

यह पूरी तरह से काम करता है और मैं सिर्फ अपनी उत्पादन वेब सर्वर पर पुनर्लेखन नियम बाहर ले।

2

कुछ चीजें जो सहायक हो सकती हैं। Where is the source for RequireHttpsAttribute?

भी एक लगभग समान वर्ग एक ही धागे पर उल्लेख किया codeplex पर RequireSslAttribute कहा जाता है:

इस सूत्र में RequireHttpsAttribute के स्रोत कोड का एक संस्करण है। http://aspnet.codeplex.com/SourceControl/changeset/view/63930#391756

यहां एक विशेषता का एक नमूना है जिसका उपयोग http से https या TargetUriScheme प्रॉपर्टी के आधार पर रिवर्स टॉगल करने के लिए किया जा सकता है। इसमें बंदरगाह संख्या निर्दिष्ट करने के लिए गुण भी शामिल हैं।

मैंने डीबग कॉन्फ़िगरेशन के तहत निर्माण करते समय अपने स्थानीय विकास बंदरगाहों को सेट करने के लिए अपने कन्स्ट्रक्टर में #if DEBUG ब्लॉक का उपयोग करना चुना है।यह मेरे लिए काम करता है क्योंकि मैं हमेशा तैनाती के दौरान रिलीज के तहत निर्माण करता हूं, इस स्थिति में बंदरगाह संख्या शून्य हो जाएगी और यूआरएल से बाहर छोड़ा जाएगा।

एक्शन विधि में विशेषता लागू करते समय पोर्ट नंबर भी सेट किए जा सकते हैं। रनटाइम पर पोर्ट नंबर निर्धारित करने के लिए मैं इन्हें कॉन्फ़िगरेशन फ़ाइल या किसी अन्य कॉन्फ़िगरेशन स्रोत पर हुकिंग भी देख सकता था।

public class ToggleHttpHttpsAttribute : FilterAttribute, IAuthorizationFilter 
{ 
    //supported uri scheme values 
    public enum UriScheme 
    { 
     Http, 
     Https 
    } 

    public ToggleHttpHttpsAttribute(
     UriScheme uriScheme = UriScheme.Http) 
    { 
     TargetUriScheme = uriScheme; 
    #if DEBUG 
     //set DEBUG ports 
     HttpPort = 55892; 
     HttpsPort = 44301; 
    #endif 
    } 

    private UriScheme TargetUriScheme { get; set; } 
    public int? HttpPort { get; set; } 
    public int? HttpsPort { get; set; } 

    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if(filterContext == null) 
     { 
      throw new ArgumentNullException("filterContext"); 
     } 

     bool isHttps = filterContext.HttpContext.Request.IsSecureConnection; 

     if ((isHttps && TargetUriScheme == UriScheme.Http) || (!isHttps && TargetUriScheme == UriScheme.Https)) 
     { 
      ToggleUriScheme(filterContext); 
     } 
    } 

    private void ToggleUriScheme(AuthorizationContext filterContext) 
    { 
     //only allow toggle if GET request 
     if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) 
     { 
      throw new InvalidOperationException("ToggleHttpHttpsAttribute can only be used on GET requests."); 
     } 

     filterContext.Result = GetRedirectResult(filterContext); 
    } 

    private RedirectResult GetRedirectResult(AuthorizationContext filterContext) 
    { 
     string prefix = TargetUriScheme == UriScheme.Http 
      ? "http://" 
      : "https://"; 

     int? port = TargetUriScheme == UriScheme.Http 
      ? HttpPort 
      : HttpsPort; 

     string url = string.Format(
      "{0}{1}{2}{3}", 
      prefix, 
      filterContext.HttpContext.Request.Url.Host, 
      port == null ? "" : string.Format(":{0}", port), 
      filterContext.HttpContext.Request.RawUrl); 

     return new RedirectResult(url); 
    } 
} 
2

मैं इस एक ही मुद्दा है, और मैं Web.config में दोनों RequireHttpsAttribute और कोई URL रीराइट नियम का उपयोग करके इसे सुलझाने रहा हूँ। पुनर्लेखन नियम गैर मानक पोर्ट संख्याओं से मेल खाता है, और विशेषता से आगे निष्पादित करता है। आप तैनाती पर पुनर्लेखन नियम को हटाने के लिए Web.config ट्रांसफॉर्म का उपयोग कर सकते हैं, लेकिन यदि आप इसे छोड़ देते हैं तो इसका कोई प्रभाव नहीं होना चाहिए। उत्पादन में आप मानक पोर्ट नंबर का उपयोग करेंगे कि नियम मेल नहीं खाएगा। फिर विशेषता इसे पकड़ लेगी।

यहाँ नियम है:

<system.webServer> 
    <rewrite> 
    <rules> 
    <!-- Redirect HTTP requests to HTTPS, using the non-standard development ports. 
    On deployment, this rule is removed, and the RequireHttpAttribute filter globally applied 
    in SlicerWeb.FilterConfig takes over. This rewrite rule executes before the attribute 
    would be applied, and so can apply the port numbers --> 
     <rule name="HTTPS redirect" stopProcessing="true"> 
     <match url="(.*)" /> 
     <conditions> 
      <add input="{HTTPS}" pattern="off" ignoreCase="true" /> 
      <add input="{SERVER_PORT}" pattern="60470" /> 
     </conditions> 
     <action type="Redirect" url="https://{SERVER_NAME}:44300/{R:1}" redirectType="Found" /> 
     </rule> 
    </rules> 
    </rewrite> 
</system.webServer> 

इस दृष्टिकोण के लिए नकारात्मक पक्ष यह है कि आप जब स्थानीय स्तर पर चल रहा है विशेषता पर भरोसा नहीं कर रहे हैं है। लेकिन अगर आपने इसे वैश्विक स्तर पर एक बार लागू किया है, तो इसे प्रत्येक नियंत्रक में जोड़ने की बजाय, यह मेरी राय में ठीक है।