मैं इस सवाल पर आगे बढ़ा और आशा करता हूं कि मेरा समाधान किसी की मदद कर सकता है।
हमें कुछ समस्याएं मिलीं: - हमें "खाता" में "लॉगऑन" उदाहरण के लिए, विशिष्ट कार्यों को सुरक्षित करने की आवश्यकता है। हम बिल्ड का उपयोग आवश्यकताएँ आवश्यकताएँ में कर सकते हैं, जो बहुत अच्छा है - लेकिन यह हमें https: // के साथ वापस भेज देगा। - हमें अपने लिंक, फॉर्म और इस तरह के "एसएसएल को अवगत" कराना चाहिए।
आम तौर पर, मेरा समाधान उन मार्गों को निर्दिष्ट करने की अनुमति देता है जो प्रोटोकॉल को निर्दिष्ट करने की क्षमता के अलावा, पूर्ण यूआरएल का उपयोग करेंगे। "Https" प्रोटोकॉल को निर्दिष्ट करने के लिए आप इस दृष्टिकोण का उपयोग कर सकते हैं।
तो, सबसे पहले मैंने एक कनेक्शनप्रोटोकॉल एनम बनाया है:
public enum ConnectionProtocol
{
Ignore,
Http,
Https
}
अब, मैंने NeedSsl का हैंड-रोल्ड वर्जन बनाया है। मैंने http: // urls पर पुनर्निर्देशन की अनुमति देने के लिए मूल आवश्यकताएँ एसएलएसएल स्रोत कोड को संशोधित किया है। इसके अलावा, मैंने एक फ़ील्ड डाल दी है जो हमें यह निर्धारित करने की अनुमति देता है कि क्या हमें एसएसएल की आवश्यकता है या नहीं (मैं इसका उपयोग डेबग प्री-प्रोसेसर के साथ कर रहा हूं)।
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public sealed class RequireHttpsAttribute : FilterAttribute, IAuthorizationFilter
{
public RequireHttpsAttribute()
{
Protocol = ConnectionProtocol.Ignore;
}
public ConnectionProtocol Protocol { get; set; }
public bool SecureConnectionsAllowed
{
get
{
#if DEBUG
return false;
#else
return true;
#endif
}
}
public void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!SecureConnectionsAllowed)
return;
switch (Protocol)
{
case ConnectionProtocol.Https:
if (!filterContext.HttpContext.Request.IsCurrentConnectionSecured())
{
HandleNonHttpsRequest(filterContext);
}
break;
case ConnectionProtocol.Http:
if (filterContext.HttpContext.Request.IsCurrentConnectionSecured())
{
HandleNonHttpRequest(filterContext);
}
break;
}
}
private void HandleNonHttpsRequest(AuthorizationContext filterContext)
{
if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("The requested resource can only be accessed via SSL.");
}
string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult(url);
}
private void HandleNonHttpRequest(AuthorizationContext filterContext)
{
if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("The requested resource can only be accessed without SSL.");
}
string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult(url);
}
}
अब, यह आवश्यकताएँ आपकी आवश्यकताओं विशेषता मूल्य के आधार पर निम्नलिखित कार्य करेगी: - ध्यान न दें: कुछ भी न करें। - Http: http प्रोटोकॉल में पुनर्निर्देशन के लिए बाध्य करेगा। - Https: https प्रोटोकॉल में पुनर्निर्देशन को मजबूर करेगा।
आपको अपना आधार नियंत्रक बनाना चाहिए और इस विशेषता को Http पर सेट करना चाहिए।
[RequireSsl(Requirement = ConnectionProtocol.Http)]
public class MyController : Controller
{
public MyController() { }
}
अब, प्रत्येक cpntroller / कार्रवाई में आपको SSL की आवश्यकता होगी - बस इस विशेषता को ConnectionProtocol.Https के साथ सेट करें।
अब URLs पर जाने देता है: हमें url रूटिंग इंजन के साथ कुछ समस्याएँ हुईं। आप उनके बारे में http://blog.stevensanderson.com/2008/08/05/adding-httpsssl-support-to-aspnet-mvc-rout/ पर अधिक पढ़ सकते हैं । इस पोस्ट में सुझाया गया समाधान सैद्धांतिक रूप से अच्छा है, लेकिन पुराना है और मुझे यह पसंद नहीं है।
मेरे समाधान निम्नलिखित हैं: मूल "रूट" वर्ग का एक उपवर्ग बनाएँ:
सार्वजनिक वर्ग AbsoluteUrlRoute: रूट {#region ctor
public AbsoluteUrlRoute(string url, IRouteHandler routeHandler)
: base(url, routeHandler)
{
}
public AbsoluteUrlRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
: base(url, defaults, routeHandler)
{
}
public AbsoluteUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints,
IRouteHandler routeHandler)
: base(url, defaults, constraints, routeHandler)
{
}
public AbsoluteUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints,
RouteValueDictionary dataTokens, IRouteHandler routeHandler)
: base(url, defaults, constraints, dataTokens, routeHandler)
{
}
#endregion
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
var virtualPath = base.GetVirtualPath(requestContext, values);
if (virtualPath != null)
{
var scheme = "http";
if (this.DataTokens != null && (string)this.DataTokens["scheme"] != string.Empty)
{
scheme = (string) this.DataTokens["scheme"];
}
virtualPath.VirtualPath = MakeAbsoluteUrl(requestContext, virtualPath.VirtualPath, scheme);
return virtualPath;
}
return null;
}
#region Helpers
private string MakeAbsoluteUrl(RequestContext requestContext, string virtualPath, string scheme)
{
return string.Format("{0}://{1}{2}{3}{4}",
scheme,
requestContext.HttpContext.Request.Url.Host,
requestContext.HttpContext.Request.ApplicationPath,
requestContext.HttpContext.Request.ApplicationPath.EndsWith("/") ? "" : "/",
virtualPath);
}
#endregion
}
"रूट" वर्ग का यह संस्करण पूर्ण यूआरएल बनाएगा। यहाँ पर ट्रिक, ब्लॉग पोस्ट लेखक के सुझाव के बाद, स्कीम को निर्दिष्ट करने के लिए DataToken का उपयोग करना है (उदाहरण के अंत में :))।
अब, यदि हम एक url उत्पन्न करेंगे, उदाहरण के लिए "खाता / लॉगऑन" मार्ग के लिए "हम प्राप्त करेंगे" / http://example.com/Account/LogOn "- चूंकि UrlRoutModule सभी url को सापेक्ष रूप में देखता है। हम कस्टम HttpModule का उपयोग करके इसे ठीक कर सकते हैं:
public class AbsoluteUrlRoutingModule : UrlRoutingModule
{
protected override void Init(System.Web.HttpApplication application)
{
application.PostMapRequestHandler += application_PostMapRequestHandler;
base.Init(application);
}
protected void application_PostMapRequestHandler(object sender, EventArgs e)
{
var wrapper = new AbsoluteUrlAwareHttpContextWrapper(((HttpApplication)sender).Context);
}
public override void PostResolveRequestCache(HttpContextBase context)
{
base.PostResolveRequestCache(new AbsoluteUrlAwareHttpContextWrapper(HttpContext.Current));
}
private class AbsoluteUrlAwareHttpContextWrapper : HttpContextWrapper
{
private readonly HttpContext _context;
private HttpResponseBase _response = null;
public AbsoluteUrlAwareHttpContextWrapper(HttpContext context)
: base(context)
{
this._context = context;
}
public override HttpResponseBase Response
{
get
{
return _response ??
(_response =
new AbsoluteUrlAwareHttpResponseWrapper(_context.Response));
}
}
private class AbsoluteUrlAwareHttpResponseWrapper : HttpResponseWrapper
{
public AbsoluteUrlAwareHttpResponseWrapper(HttpResponse response)
: base(response)
{
}
public override string ApplyAppPathModifier(string virtualPath)
{
int length = virtualPath.Length;
if (length > 7 && virtualPath.Substring(0, 7) == "/http:/")
return virtualPath.Substring(1);
else if (length > 8 && virtualPath.Substring(0, 8) == "/https:/")
return virtualPath.Substring(1);
return base.ApplyAppPathModifier(virtualPath);
}
}
}
}
चूंकि यह मॉड्यूल UrlRoutModule के आधार कार्यान्वयन को ओवरराइड कर रहा है, इसलिए हमें आधार httpModule को हटा देना चाहिए और web.config में अपना पंजीकरण करना चाहिए। तो, "system.web" सेट के तहत:
<httpModules>
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0" type="MyApp.Web.Mvc.Routing.AbsoluteUrlRoutingModule" />
</httpModules>
बस :)।
मार्ग का निरपेक्ष / प्रोटोकॉल दर्ज करने के लिए, आपको यह करना चाहिए:
routes.Add(new AbsoluteUrlRoute("Account/LogOn", new MvcRouteHandler())
{
Defaults = new RouteValueDictionary(new {controller = "Account", action = "LogOn", area = ""}),
DataTokens = new RouteValueDictionary(new {scheme = "https"})
});
आपकी प्रतिक्रिया + सुधार सुनना पसंद करेंगे। आशा है कि यह मदद कर सकता है! :)
संपादित करें: मैं IsCurrentConnectionSecured () विस्तार विधि (बहुत अधिक स्निपेट: पी) शामिल करना भूल गया। यह एक विस्तार विधि है जो आम तौर पर Request.IsSecuredConnection का उपयोग करती है। हालांकि, लोड-बैलेंसिंग का उपयोग करते समय यह एप्रोच काम नहीं करेगा - इसलिए यह विधि इस को बायपास कर सकती है (nopCommerce से लिया गया)।
public static bool IsCurrentConnectionSecured(this HttpRequestBase request)
{
return request != null && request.IsSecureConnection;
}