有没有办法要求WebApi使用SSL?属性?
我在下看不到适用的属性System.Web.Http
,类似于RequireHttps
MVC的属性。如果有内置的解决方案,我只是想避免滚动自己的属性/消息处理程序。
Answers:
您可以使用WebAPIContrib项目中的RequireHttpsHandler。基本上,它所做的就是检查传入的请求URI方案:
if (request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
// Forbidden (or do a redirect)...
}
另外,Carlos Figueira在他的MSDN博客上还有另一个实现。
public class RequireHttpsAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
}
}
}
ActionFilterAttribute
此代码使用的类也位于中System.Web.Http.Filters
。这不是中的ActionFilterAttribute
类System.Web.Mvc
。
[RequireHttps]
到您的类/动作上方。文件:asp.net/web-api/overview/security/working-with-ssl-in-web-api
令人困惑的是,ASP.NET Web API中没有与ASP.NET MVC RequireHttps属性等效的属性。但是,您可以基于MVC的RequireHttps轻松创建一个。
using System;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
...
public class RequireHttpsAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
if (actionContext == null)
{
throw new ArgumentNullException("actionContext");
}
if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
HandleNonHttpsRequest(actionContext);
}
else
{
base.OnAuthorization(actionContext);
}
}
protected virtual void HandleNonHttpsRequest(HttpActionContext actionContext)
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
actionContext.Response.ReasonPhrase = "SSL Required";
}
}
剩下要做的就是争论有多少冗余代码。
您可以使用以下过滤器类来强制您的操作方法使用SSL,这将使用GET方法或任何其他动词来处理您的请求,如果使用get方法,则会将浏览器(使用位置标头)重定向到新URI。否则将显示一条消息,使用https
下面的代码显示从AuthorizationFilterAttribute继承后,您必须重写OnAuthorization方法。
string _HtmlBody = string.Empty;
UriBuilder httpsNewUri;
var _Request = actionContext.Request;
if (_Request.RequestUri.Scheme != Uri.UriSchemeHttps )
{
_HtmlBody = "<p>Https is required</p>";
if (_Request.Method.Method == "GET"){
actionContext.Response = _Request.CreateResponse(HttpStatusCode.Found);
actionContext.Response.Content = new StringContent(_HtmlBody, Encoding.UTF8, "text/html");
httpsNewUri = new UriBuilder(_Request.RequestUri);
httpsNewUri.Scheme = Uri.UriSchemeHttps;
httpsNewUri.Port = 443;
//To ask a web browser to load a different web page with the same URI but different scheme and port
actionContext.Response.Headers.Location = httpsNewUri.Uri;
}else{
actionContext.Response = _Request.CreateResponse(HttpStatusCode.NotFound);
actionContext.Response.Content = new StringContent(_HtmlBody, Encoding.UTF8, "text/html");
}
}
经过一些研究,我确定这可能是最适当的应对措施。尽管指定了建议使用Html,但可以将其更新为提供json,文本或xml。
public class RequireHttpsAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext context)
{
if (context.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
context.Response = new HttpResponseMessage(HttpStatusCode.UpgradeRequired);
context.Response.Headers.Add("Upgrade", "TLS/1.1, HTTP/1.1");
context.Response.Headers.Add("Connection", "Upgrade");
context.Response.Headers.Remove("Content-Type");
context.Response.Headers.Add("Content-Type", "text/html");
context.Response.Content = new StringContent("<html><head></head><body><h1>Http protocol is not valid for this service call.</h1><h3>Please use the secure protocol https.</h3></body></html>");
}
else base.OnAuthorization(context);
}
}
这是规范:RFC 2817
您可以使用以下代码;(自动重定向到https)在发出基于http的请求时重定向到https。
要在Visual Studio中进行检查,您需要在Visual Studio中启用ssl。这可以通过将enable ssl属性设置为true来完成。
public class RequireHttpsAttribute: AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
if(actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
// constructing the https url
var uriBuilder = new UriBuilder(actionContext.Request.RequestUri)
{
Scheme = Uri.UriSchemeHttps,
Port = 44353 // port used in visual studio for this
};
actionContext.Response.Headers.Location = uriBuilder.Uri;
}
}
}
像这样在Register方法中使用
config.Filters.Add(new RequireHttpsAttribute());