【问题标题】:Asp.Net Core Google authenticationAsp.Net Core 谷歌认证
【发布时间】:2017-05-09 02:34:49
【问题描述】:

我的应用在 Google Compute Engine 上运行。 Nginx 用作代理服务器。 Nginx 被配置为使用 SSL。下面是/etc/nginx/sites-available/default的内容:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name mywebapp.com;
    return 301 https://$server_name$request_uri;
}
server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    include snippets/ssl-mywebapp.com.conf;
    include snippets/ssl-params.conf;
    root /home/me/MyWebApp/wwwroot;
    location /.well-known/ {
    }
    location / {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

在 Startup.cs 我有:

app.UseGoogleAuthentication(new GoogleOptions()
{
    ClientId = Configuration["Authentication:Google:ClientId"],
    ClientSecret = Configuration["Authentication:Google:ClientSecret"],
});

现在在 Google Cloud Platform 中,我需要指定授权重定向 URI。如果我输入以下内容,我的网络应用程序将按预期工作:

http://mywebapp.com/signin-google

但是,如果使用https,它将不起作用;浏览器显示如下错误:

The redirect URI in the request, http://mywebapp.com/signin-google, does
not match the ones authorized for the OAuth client.

在这种情况下,使用 http 作为授权重定向 uri 是否安全?如果我希望它是 https,我需要什么配置?

【问题讨论】:

    标签: nginx asp.net-core google-cloud-platform google-sso


    【解决方案1】:

    发生这种情况是因为您在反向代理服务器后面运行的应用程序不知道最初的请求是通过 HTTPS 来的。

    SSL/TLS 终止代理

    问题中描述的反向代理的配置称为 SSL/TLS 终止反向代理。这意味着在客户端和代理服务器之间建立了安全流量。代理服务器解密请求,然后通过 HTTP 协议将其转发给应用程序。

    此配置的问题在于其背后的应用程序不知道客户端通过 HTTPS 发送请求。因此,当涉及到重定向到自身时,它使用HttpContext.Request.SchemeHttpContext.Request.HostHttpContext.Request.Port 来构建有效的重定向 URL。

    X-Forwarded-* HTTP 标头

    这就是X-Forwarded-* 标头发挥作用的地方。为了让应用程序知道请求最初是通过 HTTPS 上的代理服务器发出的,我们必须配置代理服务器以设置 X-Forwarded-ForX-Forwarded-Proto HTTP 标头。

    location / {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
    

    好的,现在如果我们回到 ASP.NET Core 应用程序并查看传入的 HTTP 请求,我们将看到两个 X-Forwarded-* 标头集,但是重定向 URL 仍然使用 HTTP 方案。

    转发标头中间件

    基本上,此中间件将HttpContext.Request.SchemeHttpContext.Connection.RemoteIpAddress 覆盖为X-Forwarded-ProtoX-Forwarded-For 标头提供的值。为了实现这一点,让我们通过在 Startup.Configure() 方法开头的某处添加以下行来将其添加到管道中。

            var forwardedHeadersOptions = new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
                RequireHeaderSymmetry = false
            };
            forwardedHeadersOptions.KnownNetworks.Clear();
            forwardedHeadersOptions.KnownProxies.Clear();
    
            app.UseForwardedHeaders(forwardedHeadersOptions);
    

    这最终会使您的应用程序使用 HTTPS 方案构造有效的 URL。

    我的故事

    上面的代码看起来与 Microsoft 建议的不同。如果我们看一下documentation,他们的代码看起来会短一些:

    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
         ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
    });
    

    但是这对我不起作用。另外根据this issue 下的cmets,我并不孤单。

    我将 nginx 设置为在 Docker 容器中运行的 ASP.NET Core 应用程序的反向代理。在我将所有内容都放在 Amazon 负载均衡器 (ELB) 之后,情况变得更加复杂。

    我首先遵循了文档中的建议,但它对我不起作用。我的应用中出现以下警告:

    X-Forwarded-For 和 X-Forwarded-Proto 之间的参数计数不匹配

    然后我查看了我的 X-Forwarded-* 标头并意识到它们的长度不同。 X-Forwarded-For 标头包含 2 条记录(逗号分隔的 IP 地址),而 X-Forwarded-Proto 仅包含一条记录 https。这就是我将属性RequireHeaderSymmetry 设置为false 的方法。

    好吧,我摆脱了“参数计数...”警告消息,但紧接着我又遇到了另一个奇怪的调试消息:

    未知代理:172.17.0.6:44624

    查看ForwardedHeadersMiddleware 的源代码后,我终于发现我必须清理KnownNetworksKnownProxiesForwardedHeadersOptions 集合,或者将我的docker 网络172.17.0.1/16 添加到列表中的已知网络。在那之后,我终于让它工作了。

    PS:对于那些在负载均衡器(例如 Amazon 负载均衡器或 ELB)上设置 SSL/TLS 终止的用户不要在 nginx 配置中设置标头 X-Forwarded-Proto。这将覆盖来自负载平衡到http 方案的正确https 值,并且重定向url 将是错误的。我还没有找到如何将 nginx 中使用的方案附加到标头而不是覆盖它。

    【讨论】:

    • 谢谢你。我最近将一个项目从 Core 1.0 迁移到 2.0,并且旧项目中的自定义中间件组合不再起作用(这是对 context.Request 的简单标头检查,基于转发的标头执行context.Request.Scheme = "https")。您的解决方案让我们的 OAuth 提供程序再次运行。
    • 我确认从当前版本开始,可以在此处找到:github.com/dotnet/aspnetcore/blob/… 仍然检查 KnownNetwors 和 KnownProxies,因此仍然需要以下代码:forwardedHeadersOptions.KnownNetworks.Clear(); forwardedHeadersOptions.KnownProxies.Clear();
    • 这为我节省了大量时间(在花费大量时间之后)。从我的 asp.net 核心应用程序旁边的 nginx sidecar 中删除 Forwarded-Proto,它位于 ssl 终止负载均衡器后面,通过帮助 kestrel 使用正确的方案编写 url,使外部登录工作!
    • @alexy 给你,丹佛有啤酒在等你,如果你能到这个世界的地方。
    【解决方案2】:

    对于apache用户,只需要添加一个header: RequestHeader 设置 X-Forwarded-Proto "https"

    首先需要确保 mod_headers 已启用。

    【讨论】:

      猜你喜欢
      • 2022-01-27
      • 2023-03-05
      • 1970-01-01
      • 2023-03-17
      • 2014-02-22
      • 2011-05-11
      • 2014-10-05
      • 2019-06-26
      相关资源
      最近更新 更多