프로덕션에서만 ASP.NET MVC HttpsRequires
보안되지 않은 HTTP 요청이 조치 메소드로 전송되지 않도록 RequireHttpsAttribute 를 사용하고 싶습니다 .
씨#
[RequireHttps] //apply to all actions in controller
public class SomeController
{
[RequireHttps] //apply to this action only
public ActionResult SomeAction()
{
...
}
}
VB
<RequireHttps()> _
Public Class SomeController
<RequireHttps()> _
Public Function SomeAction() As ActionResult
...
End Function
End Class
불행히도 ASP.NET Development Server는 HTTPS를 지원하지 않습니다.
프로덕션 환경에 게시 할 때 ASP.NET MVC 응용 프로그램에서 RequireHttps를 사용하도록하려면 어떻게해야합니까? 그러나 ASP.NET 개발 서버의 개발 워크 스테이션에서는 실행할 수 없습니까?
개발 워크 스테이션에서 릴리스 빌드를 실행하면 도움이되지 않지만 조건부 컴파일이 작업을 수행 할 수 있습니다.
#if !DEBUG
[RequireHttps] //apply to all actions in controller
#endif
public class SomeController
{
//... or ...
#if !DEBUG
[RequireHttps] //apply to this action only
#endif
public ActionResult SomeAction()
{
}
}
최신 정보
Visual Basic에서 특성은 기술적으로 적용되는 정의와 같은 줄의 일부입니다. 조건부 컴파일 문을 줄 안에 넣을 수 없으므로 함수 선언과 속성없이 한 번, 함수 선언을 두 번 작성해야합니다. 그러나 추악함을 신경 쓰지 않으면 작동합니다.
#If Not Debug Then
<RequireHttps()> _
Function SomeAction() As ActionResult
#Else
Function SomeAction() As ActionResult
#End If
...
End Function
업데이트 2
여러 사람들이 RequireHttpsAttribute
모범을 제시하지 않고 파생한다고 언급 했으므로 여기에 있습니다. 나는이 접근법이 조건부 컴파일 방식보다 훨씬 깨끗하다고 생각하며, 당신의 입장에서 내가 선호하는 것입니다.
면책 조항 : 나는이 코드를 조금도 테스트하지 않았으며 VB는 상당히 녹슬 었습니다. 내가 아는 전부는 컴파일된다는 것입니다. 나는 spot, queen3, Lance Fisher의 제안에 근거하여 썼습니다. 작동하지 않으면 최소한 일반적인 아이디어를 전달하고 시작점을 제공해야합니다.
Public Class RemoteRequireHttpsAttribute
Inherits System.Web.Mvc.RequireHttpsAttribute
Public Overrides Sub OnAuthorization(ByVal filterContext As _
System.Web.Mvc.AuthorizationContext)
If IsNothing(filterContext) Then
Throw New ArgumentNullException("filterContext")
End If
If Not IsNothing(filterContext.HttpContext) AndAlso _
filterContext.HttpContext.Request.IsLocal Then
Return
End If
MyBase.OnAuthorization(filterContext)
End Sub
End Class
기본적으로 현재 요청이 로컬 인 경우 (즉, localhost를 통해 사이트에 액세스하는 경우) 기본 SSL 인증 코드를 실행하는 대신 새 속성이 종료됩니다. 다음과 같이 사용할 수 있습니다.
<RemoteRequireHttps()> _
Public Class SomeController
<RemoteRequireHttps()> _
Public Function SomeAction() As ActionResult
...
End Function
End Class
훨씬 더 깨끗합니다! 테스트되지 않은 코드가 실제로 작동한다면
누구나 C # 버전이 필요한 경우 :
using System;
using System.Web.Mvc;
namespace My.Utils
{
public class MyRequireHttpsAttribute : RequireHttpsAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.HttpContext != null && filterContext.HttpContext.Request.IsLocal)
{
return;
}
base.OnAuthorization(filterContext);
}
}
}
RequireHttps에서 파생하는 것이 좋은 방법입니다.
문제를 완전히 회피하기 위해 자체 서명 된 인증서로 로컬 컴퓨터의 IIS를 사용할 수도 있습니다. IIS는 내장 웹 서버보다 빠르며 개발 환경이 프로덕션과 유사하다는 이점이 있습니다.
Scott Hanselman은 VS2010 및 IIS Express를 사용하여 로컬 HTTPS를 구현하는 몇 가지 방법에 대한 유용한 리소스를 제공합니다.
MVC 필터 시스템과 Global.asax.cs를 활용하면이 작업을 수행 할 수 있다고 가정합니다 ...
protected void Application_Start()
{
RegisterGlobalFilters(GlobalFilters.Filters);
}
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
if(Config.IsProduction) //Some flag that you can tell if you are in your production environment.
{
filters.Add(new RequireHttpsAttribute());
}
}
처음에는 문제를 일으킨 ASP.Net Development Server 였으므로 Microsoft는 이제 Visual Studio (VS2010 SP1 이후)와 함께 제공되는 IIS Express를 보유하고 있습니다. 이것은 개발 서버만큼 사용하기 쉬운 IIS의 축소 버전이지만 SSL을 포함한 IIS 7.5의 모든 기능을 지원합니다.
Scott Hanselman은 IIS Express에서 SSL 작업 에 대한 자세한 게시물을 보유하고 있습니다.
사용자 정의 속성에서 RequireHttps 속성을 상속받는 방법은 무엇입니까? 그런 다음 사용자 지정 특성 내에서 현재 요청의 IsLocal 속성을 확인하여 요청이 로컬 컴퓨터에서 오는지 확인하십시오. 그렇다면 기본 기능을 적용하지 마십시오. 그렇지 않으면 기본 작업을 호출하십시오.
이것은 나를 위해 MVC 6 (ASP.NET Core 1.0) 일했습니다 . 코드는 디버그가 개발 중인지 확인하고, 그렇지 않은 경우 ssl이 필요하지 않습니다. 모든 편집 내용은 Startup.cs에 있습니다.
더하다:
private IHostingEnvironment CurrentEnvironment { get; set; }
더하다:
public Startup(IHostingEnvironment env)
{
CurrentEnvironment = env;
}
편집하다:
public void ConfigureServices(IServiceCollection services)
{
// additional services...
services.AddMvc(options =>
{
if (!CurrentEnvironment.IsDevelopment())
{
options.Filters.Add(typeof(RequireHttpsAttribute));
}
});
}
파생하고 재정의 할 수 있다면 그렇게하십시오. 당신이 할 수없는 경우-MVC는 소스와 함께 제공됩니다, 그냥 소스를 가져와 IsLocal을 확인하는 자신의 [ForceHttps] 특성을 만듭니다.
MVC 3의 경우 필자는 자신의 FilterProvider를 추가했습니다 (여기에서 찾은 코드를 기반으로 : 로컬 및 조건부 필터) (로컬 사용자에 대한 디버그 정보 표시 등)는 RequireHttpsAttribute
when 로 모든 작업을 장식합니다 HttpContext.Request.IsLocal == false
.
소리내어 연구 한 후 IIS Express에서이 문제를 해결하고 Controller 클래스의 OnAuthorization 메서드 (Ref # 1)를 재정의 할 수있었습니다. 또한 Hanselman (Ref # 2)이 권장하는 경로를 사용했습니다. 그러나 두 가지 이유로 인해이 두 가지 솔루션에 완전히 만족하지 못했습니다. 1. Ref # 1의 OnAuthorization은 컨트롤러 클래스 레벨이 아닌 동작 레벨에서만 작동합니다. Ref # 2에는 많은 설정이 필요합니다 (makecert 용 Win7 SDK). ), netsh 명령 및 포트 80 및 포트 443을 사용하려면 관리자로 VS2010을 시작해야합니다.
그래서 나는 다음과 같은 조건에서 단순성에 중점을 둔이 솔루션을 생각해 냈습니다.
Controller 클래스 또는 작업 수준에서 RequireHttps attbbute를 사용할 수 있기를 원합니다.
RequireHttps 속성이 존재할 때 MVC가 HTTPS를 사용하고 HTTP가없는 경우 HTTP를 사용하고 싶습니다.
관리자 권한으로 Visual Studio를 실행하고 싶지 않습니다.
IIS Express에서 할당 한 HTTP 및 HTTPS 포트를 사용할 수 있기를 원합니다 (참고 # 1 참조)
IIS Express의 자체 서명 된 SSL 인증서를 재사용 할 수 있으며 잘못된 SSL 프롬프트가 표시되는지는 상관하지 않습니다.
개발자, 테스트 및 프로덕션에서 가능한 정확히 동일한 코드 기반과 바이너리를 사용하고 추가 설정과는 별도로 (예 : netsh, mmc cert snap-in 사용)
이제 배경과 설명을 벗어난이 코드가 누군가에게 도움이되고 시간을 절약 할 수 있기를 바랍니다. 기본적으로 Controller에서 상속하는 BaseController 클래스를 만들고이 기본 클래스에서 컨트롤러 클래스를 파생시킵니다. 지금까지이 내용을 읽었으므로이를 수행하는 방법을 알고 있다고 가정합니다. 자, 행복한 코딩!
참고 # 1 : 유용한 함수 'getConfig'를 사용하여 달성합니다 (코드 참조).
참조 # 1 : http://puredotnetcoder.blogspot.com/2011/09/requirehttps-attribute-in-mvc3.html
참조 # 2 : http://www.hanselman.com/blog/WorkingWithSSLAtDevelopmentTimeIsEasierWithIISExpress.aspx
========== 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);
}
============== 종료 코드 =================
Web.Release.Config에서 HttpPort 및 HttpsPort를 지우려면 다음을 추가하십시오 (기본값 80 및 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>
프로덕션 및 개발 워크 스테이션에서 사용할 수있는 하나의 솔루션입니다. web.config의 응용 프로그램 설정에서 선택한 옵션을 기반으로합니다.
<appSettings>
<!--Use SSL port 44300 in IIS Express on development workstation-->
<add key="UseSSL" value="44300" />
</appSettings>
SSL을 사용하지 않으려면 키를 제거하십시오. 표준 SSL 포트 443을 사용하는 경우 값을 제거하거나 443을 지정하십시오.
그런 다음 조건을 처리하는 RequireHttpsAttribute의 사용자 정의 구현을 사용 하십시오. 실제로 RequireHttps 에서 파생되며 조건 추가를 제외하고 동일한 기본 메소드 구현을 사용합니다.
public class RequireHttpsConditional : RequireHttpsAttribute
{
protected override void HandleNonHttpsRequest(AuthorizationContext filterContext)
{
var useSslConfig = ConfigurationManager.AppSettings["UseSSL"];
if (useSslConfig != null)
{
if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("The requested resource can only be accessed via SSL.");
}
var request = filterContext.HttpContext.Request;
string url = null;
int sslPort;
if (Int32.TryParse(useSslConfig, out sslPort) && sslPort > 0)
{
url = "https://" + request.Url.Host + request.RawUrl;
if (sslPort != 443)
{
var builder = new UriBuilder(url) {Port = sslPort};
url = builder.Uri.ToString();
}
}
if (sslPort != request.Url.Port)
{
filterContext.Result = new RedirectResult(url);
}
}
}
}
AccountController에서 LogOn 메소드 를 장식하는 것을 잊지 마십시오
[RequireHttpsConditional]
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
https를 통해 양식을 게시하기 위해 LogOn View에서 이와 같은 것 .
<% using (Html.BeginFormSecure("LogOn", "Account", new { ReturnUrl = Request.QueryString["ReturnUrl"] }, Request.IsSecureConnection, Request.Url)) { %>
Joel이 언급했듯이 #if !DEBUG
지시문 을 사용하여 컴파일을 변경할 수 있습니다 .
I just found out that you can alter the value of the DEBUG symbol in the web.config file compilation element. Hope that helps.
MVC 6 (ASP.NET Core 1.0):
The proper solution would be to use env.IsProduction() or env.IsDevelopment(). Read more about reason behind in this answer on how to require https only in production.
Condensed answer below (see link above to read more about design decisions) for 2 different styles:
- Startup.cs - register filter
- BaseController - attribute style
Startup.cs (register filter):
public void ConfigureServices(IServiceCollection services)
{
// TODO: Register other services
services.AddMvc(options =>
{
options.Filters.Add(typeof(RequireHttpsInProductionAttribute));
});
}
BaseController.cs (attribute style):
[RequireHttpsInProductionAttribute]
public class BaseController : Controller
{
// Maybe you have other shared controller logic..
}
public class HomeController : BaseController
{
// Add endpoints (GET / POST) for Home controller
}
RequireHttpsInProductionAttribute: Both of above are using custom attribute inheriting from RequireHttpsAttribute:
public class RequireHttpsInProductionAttribute : RequireHttpsAttribute
{
private bool IsProduction { get; }
public RequireHttpsInProductionAttribute(IHostingEnvironment environment)
{
if (environment == null)
throw new ArgumentNullException(nameof(environment));
this.IsProduction = environment.IsProduction();
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (this.IsProduction)
base.OnAuthorization(filterContext);
}
protected override void HandleNonHttpsRequest(AuthorizationContext filterContext)
{
if(this.IsProduction)
base.HandleNonHttpsRequest(filterContext);
}
}
이것은 가장 깨끗한 방법이었습니다. 내 App_Start\FilterConfig.cs
파일에서. 더 이상 릴리스 빌드를 실행할 수 없습니다.
...
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
if (!Web.HttpContext.Current.IsDebuggingEnabled) {
filters.Add(new RequireHttpsAttribute());
}
...
}
또는 사용자 정의 오류 페이지가 켜져있을 때 https 만 요구하도록 설정할 수 있습니다.
...
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
if (Web.HttpContext.Current.IsCustomErrorEnabled) {
filters.Add(new RequireHttpsAttribute());
}
...
}
릭 앤더슨의 Azure 및 MVC의 RickAndMSFT에서이 게시물을 참조하십시오.
참고 URL : https://stackoverflow.com/questions/1639707/asp-net-mvc-requirehttps-in-production-only
'Programming' 카테고리의 다른 글
git mv 실행 취소 (이름 바꾸기) (0) | 2020.07.12 |
---|---|
Xcode : 장치 지원 파일을 찾을 수 없습니다 (0) | 2020.07.12 |
새로운 Rails 프로젝트에서 SQLite에서 PostgreSQL로 변경 (0) | 2020.07.11 |
RESTful 웹 서비스가 필요한 이유는 무엇입니까? (0) | 2020.07.11 |
스칼라 변수에 대한 SQL Server 출력 절 (0) | 2020.07.11 |