我想使用RequireHttpsAttribute来防止将不安全的HTTP请求发送到操作方法 .
C#
[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 Development Server上的开发工作站上运行时?
15 回答
如果您在开发工作站上运行Release版本,这将无济于事,但条件编译可以完成这项工作......
更新
在Visual Basic中,属性在技术上与它们应用的定义属于同一行 . 你不能把条件编译语句放在一行中,所以你被迫写两次函数声明 - 一次使用属性,一次不使用 . 但是,如果你不介意丑陋,它确实有效 .
更新2
有几个人提到从
RequireHttpsAttribute
派生而没有提供一个例子,所以这里有一个给你 . 我认为这种方法比条件编译方法更清晰,而且我的偏好是你的立场 .免责声明:我没有测试过这段代码,甚至一点点,我的VB相当生疏 . 我所知道的只是它编译 . 我是根据spot,queen3和Lance Fisher的建议写的 . 如果它不起作用,它至少应该传达一般的想法,并给你起点 .
基本上,如果当前请求是本地请求(即,您通过localhost访问该站点),则新属性将退出而不是运行默认SSL授权代码 . 你可以像这样使用它:
更干净!如果我未经测试的代码实际上有效 .
如果有人需要C#版本:
从RequireHttps派生是一种很好的方法 .
要完全解决问题,您也可以在本地计算机上使用带有自签名证书的IIS . IIS比内置的Web服务器更快,您的优势在于您的开发环境更像是 生产环境 环境 .
Scott Hanselman has a great resource on a few ways to implement local HTTPS with VS2010 and IIS Express.
利用MVC过滤系统和Global.asax.cs,我假设你可以这样做......
由于ASP.Net开发服务器首先引起了您的问题,因此值得注意的是Microsoft现在有IIS Express,它随Visual Studio一起提供(自VS2010 SP1起) . 这是IIS的简化版本,与开发服务器一样易于使用,但支持IIS 7.5的完整功能集,包括SSL .
Scott Hanselman在working with SSL in IIS Express上有详细的帖子 .
如何在自定义属性中继承RequireHttps属性 . 然后,在自定义属性中,检查当前请求的IsLocal属性,以查看请求是否来自本地计算机 . 如果是,则不应用基本功能 . 否则,调用基本操作 .
这对我有用, MVC 6 (ASP.NET Core 1.0) . 代码检查调试是否正在开发中,如果没有,则不需要ssl . 所有修改都在 Startup.cs 中 .
加:
加:
编辑:
如果你可以派生和覆盖 - 做它 . 如果你不能 - MVC附带源代码,只需获取源代码并创建自己的[ForceHttps]属性来检查IsLocal .
对于MVC 3,我添加了自己的FilterProvider(基于此处的代码:Global and Conditional Filters,除其他外(显示本地用户的调试信息等)将在
HttpContext.Request.IsLocal == false
时用RequireHttpsAttribute
装饰所有操作 .在研究了aroud之后,我能够用IIS Express解决这个问题并覆盖Controller类的OnAuthorization方法(Ref#1) . 我也选择了Hanselman推荐的路线(参考文献#2) . 但是,由于两个原因,我对这两个解决方案并不完全满意:1 . Ref#1的OnAuthorization仅适用于动作级别,而不适用于控制器级别2. Ref#2需要大量设置(适用于makecert的Win7 SDK) ),netsh命令,并且,为了使用端口80和端口443,我需要以管理员身份启动VS2010,我不赞成 .
所以,我想出了这个解决方案,它注重简单性,具备以下条件:
我希望能够在Controller类或操作级别使用RequireHttps attbbute
我希望MVC在RequireHttps属性存在时使用HTTPS,如果不存在则使用HTTP
我不想将Visual Studio作为运行管理员
我希望能够使用IIS Express分配的任何HTTP和HTTPS端口(参见注释#1)
我可以重用IIS Express的自签名SSL证书,如果看到无效的SSL提示,我不在乎
我希望dev,test和production具有完全相同的代码库和相同的二进制文件,并且与其他设置(例如,使用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中的代码===================
==============结束代码================
在Web.Release.Config中,添加以下内容以清除HttpPort和HttpsPort(使用默认的80和443) .
您可以在 生产环境 和开发工作站上使用的一种解决方案 . 它基于您在web.config中的应用程序设置中的选项
如果您不想使用SSL,请删除密钥 . 如果使用标准SSL端口443,则删除该值或指定443 .
然后使用RequireHttpsAttribute的自定义实现来处理您的情况 . 它实际上是从RequireHttps派生出来的,除了添加条件外,它使用基本方法的相同实现 .
不要忘记在AccountController中装饰LogOn方法
在LogOn视图中使用类似的东西,以便通过https发布表单 .
正如Joel所说,您可以使用
#if !DEBUG
指令更改编译 .我刚刚发现您可以在web.config文件编译元素中更改DEBUG符号的值 . 希望有所帮助 .
MVC 6 (ASP.NET Core 1.0):
正确的解决方案是使用env.IsProduction()或env.IsDevelopment() . 在how to require https only in production上阅读有关此答案背后的原因的更多信息 .
以下简明回答(请参阅上面的链接,了解有关设计决策的更多信息),有两种不同的风格:
Startup.cs - 注册过滤器
BaseController - 属性样式
Startup.cs (注册过滤器):
BaseController.cs (属性样式):
RequireHttpsInProductionAttribute :以上两者都使用从RequireHttpsAttribute继承的自定义属性:
这对我来说是最干净的方式 . 在我的
App_Start\FilterConfig.cs
文件中 . 不能再运行发布版本了 .或者,您可以将其设置为仅在启用自定义错误页面时需要https .
请参阅Rick Anderson关于Azure和MVC填充Azure Gap的RickAndMSFT的这篇文章
http://blogs.msdn.com/b/rickandy/archive/2011/04/22/better-faster-easier-ssl-testing-for-asp-net-mvc-amp-webforms.aspx