Sau khi nghiên cứu kỹ lưỡng, tôi đã có thể giải quyết vấn đề này bằng IIS Express và ghi đè phương thức OnAuthorization của lớp Controller (Tham khảo # 1). Tôi cũng đã đi theo tuyến đường do Hanselman đề xuất (Tham khảo # 2). Tuy nhiên, tôi không hoàn toàn hài lòng với hai giải pháp này do hai lý do: 1. OnAuthorization của Ref # 1 chỉ hoạt động ở cấp hành động, không hoạt động ở cấp độ bộ điều khiển 2. Tham khảo # 2 yêu cầu nhiều thiết lập (Win7 SDK cho makecert ), các lệnh netsh, và, để sử dụng cổng 80 và cổng 443, tôi cần khởi chạy VS2010 với tư cách quản trị viên, điều này khiến tôi băn khoăn.
Vì vậy, tôi đã đưa ra giải pháp tập trung vào sự đơn giản với các điều kiện sau:
Tôi muốn có thể sử dụng phần đính kèm RequestHttps ở lớp Bộ điều khiển hoặc cấp độ hành động
Tôi muốn MVC sử dụng HTTPS khi có thuộc tính RequestHttps và sử dụng HTTP nếu không có
Tôi không muốn phải chạy Visual Studio với tư cách quản trị viên
Tôi muốn có thể sử dụng bất kỳ cổng HTTP và HTTPS nào được chỉ định bởi IIS Express (Xem Lưu ý # 1)
Tôi có thể sử dụng lại chứng chỉ SSL tự ký của IIS Express và tôi không quan tâm nếu tôi thấy lời nhắc SSL không hợp lệ
Tôi muốn nhà phát triển, thử nghiệm và sản xuất có cùng một cơ sở mã chính xác và cùng một hệ nhị phân và độc lập với thiết lập bổ sung (ví dụ: sử dụng netsh, mmc cert snap-in, v.v.) càng tốt
Bây giờ, với thông tin cơ bản và giải thích rõ ràng, tôi hy vọng mã này sẽ giúp ích cho ai đó và tiết kiệm thời gian. Về cơ bản, tạo một lớp BaseController kế thừa từ Bộ điều khiển và dẫn xuất các lớp bộ điều khiển của bạn từ lớp cơ sở này. Vì bạn đã đọc đến đây, tôi cho rằng bạn biết cách làm những điều này. Vì vậy, chúc bạn mã hóa vui vẻ!
Lưu ý # 1: Điều này đạt được bằng cách sử dụng một hàm hữu ích 'getConfig' (xem mã)
Tham khảo số 1: http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
Tham khảo # 2: http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx
========== Mã trong BaseController ===================
#region Override to reroute to non-SSL port if controller action does not have RequireHttps attribute to save on CPU
// By L. Keng, 2012/08/27
// Note that this code works with RequireHttps at the controller class or action level.
// Credit: Various stackoverflow.com posts and http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
protected override void OnAuthorization(AuthorizationContext filterContext)
{
// if the controller class or the action has RequireHttps attribute
var requireHttps = (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Count() > 0
|| filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Count() > 0);
if (Request.IsSecureConnection)
{
// If request has a secure connection but we don't need SSL, and we are not on a child action
if (!requireHttps && !filterContext.IsChildAction)
{
var uriBuilder = new UriBuilder(Request.Url)
{
Scheme = "http",
Port = int.Parse(getConfig("HttpPort", "80")) // grab from config; default to port 80
};
filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
}
}
else
{
// If request does not have a secure connection but we need SSL, and we are not on a child action
if (requireHttps && !filterContext.IsChildAction)
{
var uriBuilder = new UriBuilder(Request.Url)
{
Scheme = "https",
Port = int.Parse(getConfig("HttpsPort", "443")) // grab from config; default to port 443
};
filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
}
}
base.OnAuthorization(filterContext);
}
#endregion
// a useful helper function to get appSettings value; allow caller to specify a default value if one cannot be found
internal static string getConfig(string name, string defaultValue = null)
{
var val = System.Configuration.ConfigurationManager.AppSettings[name];
return (val == null ? defaultValue : val);
}
============== mã kết thúc ================
Trong Web.Release.Config, thêm phần sau để xóa HttpPort và HttpsPort (để sử dụng mặc định 80 và 443).
<appSettings>
<add key="HttpPort" value="" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
<add key="HttpsPort" value="" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
</appSettings>