在 WebApi 中需要 SSL?

Posted

技术标签:

【中文标题】在 WebApi 中需要 SSL?【英文标题】:Require SSL in WebApi? 【发布时间】:2012-07-01 05:12:09 【问题描述】:

有没有办法为 WebApi 要求 SSL?一个属性?

我在System.Web.Http 下没有看到适用的属性,类似于我们为 MVC 提供的RequireHttps 属性。如果有内置解决方案,我只是想避免滚动我自己的属性/消息处理程序。

【问题讨论】:

这是一篇关于这个问题值得一读的文章:docs.microsoft.com/en-us/aspnet/web-api/overview/security/… 【参考方案1】:
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 中。它不是System.Web.Mvc 中找到的ActionFilterAttribute 类。 对于那些想知道的人,在某处添加此内容后,在您的类/操作上方添加[RequireHttps]。文档:asp.net/web-api/overview/security/working-with-ssl-in-web-api 我也用这个方法。我见过很多使用“AuthorizationFilterAttribute”的例子。人们为什么在“ActionFilterAttribute”上使用它?? 这应该使用 AuthorizationFilterAttribute,而不是 ActionFilterAttribute。授权在管道中较早发生,并且在您到达此处时其他操作过滤器可能已经运行。查看 CularBytes 的链接【参考方案2】:

您可以使用来自 WebAPIContrib 项目的RequireHttpsHandler。基本上,它所做的只是检查传入的请求 URI 方案:

if (request.RequestUri.Scheme != Uri.UriSchemeHttps)

  // Forbidden (or do a redirect)...

另外,Carlos Figueira 在他的 MSDN 博客上有 another implementation。

【讨论】:

谢谢。我也想多了,只是不想重新发明***,如果它是内置的。【参考方案3】:

令人费解的是,在 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";
    

剩下要做的就是争论有多少冗余代码。

【讨论】:

【参考方案4】:

您可以使用以下过滤器类来强制您的操作方法使用 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");

            

【讨论】:

【参考方案5】:

经过一些研究,我确定这可能是最合适的回应。尽管规范表明建议使用 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

【讨论】:

【参考方案6】:

您可以使用以下代码; (自动重定向到 https)在发出基于 http 的请求时重定向到 https。

要在 Visual Studio 中检查它,您需要在 Visual Studio 中启用 ssl。这可以使用 enable ssl property to 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;
        
    

在这样的注册方法中使用这个

config.Filters.Add(new RequireHttpsAttribute());

【讨论】:

如果我将它部署在实时服务器上,提及端口号将无法正常工作,如果我忽略端口号,它会将默认端口号放在那里。 嗨@JamshaidKamran 你找到解决这个问题的方法了吗,我也面临这个问题

以上是关于在 WebApi 中需要 SSL?的主要内容,如果未能解决你的问题,请参考以下文章

如何调用启用 SSL 的 Web Api?

Service Fabric 多个 SSL 安全 WebAPI 和证书翻转

在*一些* WebAPI 控制器上禁用 SSL 客户端证书?

SelfHosted AspNet WebAPI 与不同项目中的控制器类

ASP.NET WebAPI HTTPS

通过 SSL 调用 Web Api 时出现 403 禁止错误