负载平衡器中断了外部登录,因为重定向uri是http(不是https)

时间:2019-05-13 01:27:58

标签: asp.net-mvc asp.net-mvc-5 asp.net-identity owin load-balancing

我正在使用ASP.NET MVC,并且正在使用MS内置模板,以允许用户使用外部ID登录到Facebook和Google。外部ID在我的生产环境(在测试中可以工作)上不起作用,并且我相信这是由于负载均衡器...(我正在负载均衡器上卸载SSL,后端服务器使用HTTP)。

我见过This Question,并且我认为,这是我的问题:登录请求包含一个returnurl,并且由于后端服务器使用的是http,因此返回网址也是http(不是https)。这是我在AccountController中谈论的方法:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
    // Request a redirect to the external login provider
    return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}

当用户尝试登录时,我可以看到redirect_uri是http(不是https):

enter image description here

我已经检查了上述问题,也检查了this one。他们俩都建议我在Startup.Auth中使用相对路径作为重定向URL,所以这就是我添加到代码中的内容(ConfigureAuth方法):

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, long>(
            validateInterval: TimeSpan.FromMinutes(30),
            regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
            getUserIdCallback: id => id.GetUserId<long>()),

        /* THIS IS THE CHANGE THAT I HAVE ADDED */
        OnApplyRedirect = context =>
        {
            /* I have tried adding a breakpoint here, but it is never hit */
            var redirectUri = new Uri(context.RedirectUri, UriKind.Absolute);

            if (redirectUri.Scheme == "http" && redirectUri.Host == context.Request.Uri.Host)
            {
                context.RedirectUri = redirectUri.PathAndQuery;
            }

            context.Response.Redirect(context.RedirectUri);
        }
    }
});

但是此更改无效,并且redirect_url仍为http。如果我在上面添加的更改上设置了断点,则断点永远不会命中...不确定哪里出了问题?

1 个答案:

答案 0 :(得分:1)

我找到了使用this questionthis github issue的解决方案:

Load Balancer将终止SSL并使用http与后端服务器进行通信,但它将原始协议(在这种情况下为https)转发到后端服务器。因此,我们可以使用x-forwarded-proto来检测后端服务器中的原始协议:

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        /* I HAVE ADDED THIS CODE */
        app.Use((context, next) =>
        {
            if (context.Request.Headers["x-forwarded-proto"] == "https")
            {
                context.Request.Scheme = "https";
            }
            return next();
        });

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, long>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
                    getUserIdCallback: id => id.GetUserId<long>())
            }
        });

        // more code...
}