使用GetDisplayUrl无法获取正确HTTPS协议的技术问题排查
问题:从HttpContext获取的URL协议始终为HTTP而非HTTPS
背景
我需要从HttpContext获取端点URL用于属性验证,要求URL完全匹配。但获取完整URL时,协议一直是HTTP而非HTTPS。测试时用Postman发起的是HTTPS请求,比如https://endpoint/id?access_token=xxx。
代码示例
public ProofKeyContextFactory Create(HttpContext httpContext) { var endpointUrl = httpContext.Request .GetDisplayUrl() .ToUpperInvariant(); _logger.LogInformation("Endpoint URL: {EndpointUrl}", endpointUrl); }
查看Lens日志时,endpointUrl显示为HTTP://ENDPOINT/ID?ACCESS_TOKEN=XXX,并非预期的HTTPS。我尝试使用httpContext.Request.Scheme,但仍返回HTTP。
请问是什么原因导致SSL协议被识别为HTTP?
补充代码
ProofKeyContextFactory 完整实现
public class ProofKeyContextFactory { private readonly ILogger<ProofKeyContextFactory> _logger; public ProofKeyContextFactory(ILogger<ProofKeyContextFactory> logger) { logger.ThrowIfNull(); _logger = logger; } public ProofKeyContext Create(HttpContext httpContext) { var endpointUrl = httpContext.Request .GetDisplayUrl() .ToUpperInvariant(); // 记录日志 _logger.LogInformation("Endpoint URL: {EndpointUrl}", endpointUrl); // 赋值给密封记录类供后续使用 return new ProofKeyContext(endpointUrl); } }
StartupExtension.cs 中的注册代码
private static IServiceCollection AddProofKeyContext(this IServiceCollection services) { services.ThrowIfNull(); services.AddHttpContextAccessor(); services.AddScoped<ProofKeyContextFactory>(); services.AddScoped<IProofKeyContext>(provider => { var httpContextAccessor = provider.GetRequiredService<IHttpContextAccessor>(); httpContextAccessor.HttpContext.ThrowIfNull(); var factory = provider.GetRequiredService<ProofKeyContextFactory>(); return factory.Create(httpContextAccessor.HttpContext); }); return services; }
原因及解决方案
这种情况最常见的原因是SSL终止在反向代理/负载均衡层,比如Nginx、AWS ALB、Azure应用网关这类组件。它们会先处理HTTPS请求,再用HTTP转发到后端的ASP.NET Core应用,导致应用直接拿到的是HTTP协议的请求。
解决方法1:配置转发头中间件
ASP.NET Core提供了ForwardedHeadersMiddleware,可以读取反向代理传递的转发头(如X-Forwarded-Proto),自动修正请求的Scheme。
在Program.cs(或Startup.cs)中添加以下配置:
var builder = WebApplication.CreateBuilder(args); // 配置转发头,处理X-Forwarded-Proto等头信息 builder.Services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; // 若反向代理是本地或可信IP,添加到KnownProxies或KnownNetworks // options.KnownProxies.Add(IPAddress.Parse("192.168.1.100")); }); var app = builder.Build(); // 必须在其他中间件之前启用转发头中间件 app.UseForwardedHeaders(); // 其他中间件配置(如app.UseRouting()等)
解决方法2:手动读取转发头
如果不想用中间件,也可以手动从请求头中获取X-Forwarded-Proto的值来构造正确的URL:
public ProofKeyContext Create(HttpContext httpContext) { var scheme = httpContext.Request.Headers.ContainsKey("X-Forwarded-Proto") ? httpContext.Request.Headers["X-Forwarded-Proto"].ToString() : httpContext.Request.Scheme; var endpointUrl = new UriBuilder(scheme, httpContext.Request.Host.Host, httpContext.Request.Host.Port ?? -1, httpContext.Request.Path, httpContext.Request.QueryString.ToString()) .Uri.ToString() .ToUpperInvariant(); _logger.LogInformation("Endpoint URL: {EndpointUrl}", endpointUrl); return new ProofKeyContext(endpointUrl); }
注意事项
- 需确保反向代理配置正确,确实传递了
X-Forwarded-Proto头,部分代理需要手动开启该配置(比如Nginx需添加proxy_set_header X-Forwarded-Proto $scheme;)。 - 若应用部署在云服务(如Azure App Service、AWS Elastic Beanstalk),这类平台通常会自动处理转发头,只需启用
ForwardedHeadersMiddleware即可。
内容的提问来源于stack exchange,提问作者whatISboolean
相关产品推荐
相关产品推荐

