在ASP.NET Core应用程序中强制使用HTTPS

536 阅读9分钟

无论你使用的是什么编程框架,HTTPS都是赋予你的网络应用安全的必要条件。但是,如果客户端用HTTP而不是HTTPS调用你的Web应用,会发生什么?你怎么能强迫它使用HTTPS呢?让我们深入研究一下ASP.NET Core提供的选项。

使用HTTPS重定向

我猜你脑海中的第一个想法是重定向HTTP请求:如果客户端使用HTTP调用你的应用程序,你的应用程序会将其重定向到以HTTPS开始的同一URL。URL重定向是一个著名的方法。网络应用程序创建一个HTTP响应,状态代码以 3和一个Location 的头,就像下面的例子一样。

HTTP/1.1 301 Moved Permanently
Location: https://www.auth0.com/

虽然这种方法并不能解决所有的安全风险,但正如你将会学到的那样,它是一个很好的起点。

幸运的是,在ASP.NET Core中,你不需要到HTTP级别去重定向你的客户的请求。你有几个选项可以选择。让我们来分析一下每一个。

RequireHttps 属性

我们要探讨的第一个方法是基于RequireHttps 属性的。你可以在你的Razor Pages应用程序中使用它来强制一个页面需要HTTPS,如下面的代码片段所示。

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorApp.Pages;

[RequireHttps]
public class PrivacyModel : PageModel
{
  //...existing code...
}

如果这个页面是通过HTTP调用的,将自动为你创建一个HTTPS重定向响应。对于Razor Pages,你只能将RequireHttps 属性应用于继承自PageModel 的类。你不能将该属性也应用于类方法。

在ASP.NET Core MVC应用程序中,你可以将RequireHttps 属性应用于从Controller 继承的类,如下面的例子。

using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using MvcApp.Models;

namespace MvcApp.Controllers;

[RequireHttps]
public class HomeController : Controller
{
  // ...existing code...
}

当该属性被附加到控制器时,HTTP重定向将被应用到它所返回的任何视图。然而,在ASP.NET Core MVC的情况下,你可以将RequireHttps 属性应用于特定的视图。例如,下面的代码显示了如何只对隐私视图要求HTTPS重定向。

using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using MvcApp.Models;

namespace MvcApp.Controllers;

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }

    [RequireHttps]
    public IActionResult Privacy()
    {
        return View();
    }
}

基于RequireHttps 属性的重定向方法是相当简单的。你可能还认为,有选择地将其应用于特定页面或视图的机会很好,因为你可以将HTTPS限制在只有机密内容的页面。

事实上,混合HTTP和HTTPS页面是一个非常糟糕的主意你的Web应用是不安全的,因为它暴露在HTTPS降级攻击之下。为了减轻这种风险,让你的Web应用的所有页面只能用HTTPS协议访问。

你可能会想到在所有页面上应用RequireHttps 属性来降低风险,但还有更好的方法,你将在下一节看到。

HTTPS重定向中间件

当你使用一个标准的ASP.NET项目模板创建一个Web应用程序时,该 Program.cs文件中包含以下代码片断中强调的方法调用。

// Program.cs

var builder = WebApplication.CreateBuilder(args);

// ...existing code...

var app = builder.Build();

// ...existing code...

app.UseHttpsRedirection();  //👈 HTTPS redirection
app.UseStaticFiles();

app.UseRouting();

// ...existing code...

UseHttpsRedirection()方法调用启用了HTTPS重定向中间件。这意味着对你的应用程序的每个请求都将被检查,并可能被中间件重定向。你不需要去寻找缺少RequireHttps 属性的页面。你的应用程序的所有页面都需要HTTPS。如果客户端用HTTP请求一个页面,它将被自动重定向到相应的基于HTTPS的URL。

启用HSTS中间件

基于的方法 UseHttpsRedirection()的方法看起来棒极了!只需在你的 Program.cs文件中的一句话,你的整个Web应用就被强制用HTTPS协议来调用。

不幸的是,虽然这种方法比混合页面要好,但你的应用程序仍然存在一些潜在的安全问题。迫使客户端在每次请求时从HTTP切换到HTTPS可能不足以防止HTTPS降级攻击。攻击者可以在客户端切换到相应的HTTPS请求之前拦截它的HTTP请求。

你需要一个方法来告诉浏览器强制使用HTTPS来请求你的Web应用的任何资源。这种方法存在:HTTP Strict-Transport-Security头(HSTS)。使用HSTS,浏览器将只在第一次使用HTTP调用你的应用程序。对同一域名的后续请求将使用HTTPS协议,即使有一个使用HTTP方案的URL存在。要了解关于HSTS的更多细节,请看这里

要在你的ASP.NET Core应用程序中启用HSTS,你只需要调用 UseHsts()方法,如下所示 Program.cs文件中的方法,如下图所示。

// Program.cs

var builder = WebApplication.CreateBuilder(args);

// ...existing code...

var app = builder.Build();

// ...existing code...

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();    //👈 Enable HSTS middleware
}

// ...existing code...

通过调用 UseHsts()方法,你就启用了HSTS中间件。当你从一个标准的ASP.NET Core模板开始构建你的应用程序时,你已经有了这段代码。

在开发环境中使用HSTS

从上面的代码中,你可能会注意到,只有在你的应用程序不在开发环境中运行时,才会启用HSTS支持。这个选择背后有一个实际的原因。

你很可能使用localhost作为你的开发环境域。如果你在开发环境中使用HSTS,你的浏览器对localhost的任何请求都将使用HTTPS。实际上,在你的开发环境中使用HTTPS是一个好的做法。但假设你的ASP.NET Core应用程序启用了HSTS。在这种情况下,它会导致你的浏览器对任何托管在localhost上的应用程序进行HTTPS请求,而不仅仅是你的ASP.NET Core应用程序,也不仅仅是一般的ASP.NET Core应用程序。如果你有一个不使用HTTPS的Angular应用程序,并在一夜之间停止工作,这可能会导致头疼。

HSTS设置包括一个过期时间,对于ASP.NET Core应用程序,默认是30天。要改变这个和其他设置,请查看官方文档

通过对一些最臭名昭著的威胁的实践探索来学习网络安全。

下载免费电子书

Security for Web Developers

HTTPS重定向和API

在这一点上,我们可以对我们的ASP.NET Core应用程序的HTTPS安全性感到满意,对吗?嗯,不是的。实际上,这取决于网络应用的类型。

HTTPS重定向方法依赖于向客户端发送一个 301或另一个 30*HTTP状态代码,无论你是使用RequireHttps 属性还是HTTPS重定向中间件。HSTS方法依赖于发送 Strict-Transport-Security标头。

这两种方法都能被标准浏览器所理解。因此,客户端是浏览器的应用程序类型,如ASP.NET Core MVC应用程序、Razor Pages应用程序和Blazor服务器应用程序,可以依赖这些方法。

然而,这些方法通常会被非浏览器客户端忽略,比如API客户端。一个移动应用程序或SPA极少会去关心 301状态代码或HSTS头的情况极为罕见。在这种情况下,你有两种替代方法来处理发出HTTP请求的客户端。

  • 忽略HTTP请求。
  • 用一个 400 Bad Request状态代码。

忽略HTTP请求

第一种方法可以用不同的方式完成。最简单的方法之一是使用 --urls``dotnet run 标志,如下图所示。

dotnet run --urls "https://localhost:7123"

这种方法允许你覆盖配置在 Properties/launchSettings.json文件中配置的URL设置,这种方法允许你覆盖ASP.NET Core项目的URL设置。

一种更加面向生产的方法是使用 "环境变量 "来覆盖这些设置。 ASPNETCORE_URLS环境变量。下面显示了如何在PowerShell中设置这个变量。

$Env: ASPNETCORE_URLS = "https://localhost:7123"

这是在bash shell中的一个例子。

export ASPNETCORE_URLS="https://localhost:7123"

请查看这篇文章,了解在ASP.NET Core中覆盖当前监听URL的其他方法。

将HTTP请求视为坏请求

为了实现坏请求的方法,你需要创建一个自定义的中间件并使用它来代替HTTPS重定向和HSTS中间件。下面的例子显示了这样一个中间件的简单版本。

// Program.cs

var builder = WebApplication.CreateBuilder(args);

// ...existing code...

var app = builder.Build();

// ...existing code...

// 👇 new code
//app.UseHttpsRedirection();
app.Use(async (context, next) => {
    if (!context.Request.IsHttps) {
        context.Response.StatusCode = StatusCodes.Status400BadRequest;
        await context.Response.WriteAsync("HTTPS required!");
    } else {
        await next(context);
    }
});
/ 👆 new code
  
app.UseStaticFiles();

app.UseRouting();

// ...existing code...

突出显示的代码表明,现有的 UseHttpsRedirection()方法调用被自定义的中间件所取代。中间件的代码只是检查当前请求是否使用HTTPS。如果不是这样,它将回复一个 400 Bad Request状态代码和一条警告说需要HTTPS的信息。

免费试用Auth0认证。开始吧→

HTTPS重定向和反向代理

如果你的ASP.NET Core应用程序直接暴露在互联网上,上述所有内容都有意义。如果你的应用程序被部署在一个有反向代理处理连接安全的环境中,就没有必要使用HTTPS重定向或HSTS中间件。

在这种情况下,你可以简单地删除 UseHttpsRedirection()UseHsts()方法的调用。这同样适用于ASP.NET Core Web API应用程序:你不需要创建一个自定义的中间件来拒绝HTTP请求。你将HTTP切换到HTTPS,并将控制权委托给反向代理。

总结

这篇文章引导你通过不同的方法来强制客户端在调用ASP.NET Core应用程序时使用HTTPS。你从简单的RequireHttps 属性开始,它在逐页的基础上重定向到基于HTTPS的请求。然后你探索了 UseHttpsRedirection()方法,它允许你将HTTPS重定向应用于你的应用程序的所有页面。

你了解到,在每个页面请求中从HTTP重定向到HTTPS并不能保证你不暴露在HTTPS降级风险中。你通过学习HSTS和HSTS方法,进一步减轻了这种风险。 UseHsts()方法。

你还了解到,HTTPS重定向和HSTS对于普通的Web应用,如ASP.NET Core MVC、Razor和Blazor应用是很好的方法,但它们不适合API。在这种情况下,你需要忽略HTTP请求或将其标记为坏请求。

最后,只有在你的部署环境没有照顾到协议切换和控制的情况下,你才需要应用所有这些措施。例如,如果你的应用程序在反向代理后面运行,你可以将所有这些检查委托给它。


© 2013-2022 Auth0公司。保留所有权利。