Балансировщик нагрузки прерывает внешний вход в систему, потому что URI перенаправления является http (не https) - PullRequest
0 голосов
/ 13 мая 2019

Я использую ASP.NET MVC, и я использую встроенный шаблон MS, чтобы позволить пользователям входить через Facebook и Google, внешний идентификатор. Внешний идентификатор не работает в моей производственной среде (работает в тестовой среде), и я полагаю, что это связано с балансировщиком нагрузки ... (я выгружаю SSL на балансировщик нагрузки, а внутренние серверы используют HTTP).

Я видел Этот вопрос , а я думаю это моя проблема: запрос на вход в систему содержит returnurl, а поскольку внутренний сервер использует http, URL-адрес возврата также 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

Я проверил вопрос, упомянутый выше, а также этот . Они оба предлагают, чтобы я использовал относительный путь для перенаправления URL в Startup.Auth, так что это то, что я добавил в свой код (метод 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 Ответ

1 голос
/ 13 мая 2019

Я нашел решение, используя этот вопрос & этот вопрос github :

Балансировщик нагрузки завершит работу 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...
}
...