负载均衡器中断外部登录,因为重定向 uri 是 http(不是 https)
Load Balancer breaks external login, because redirect uri is http (not https)
我正在使用 ASP.NET MVC,我正在使用 MS 内置模板以允许用户使用 Facebook 和 Google、外部 ID 登录。外部 ID 在我的生产环境中不起作用(在测试中起作用),我相信这是因为负载平衡器...(我在负载平衡器上卸载 SSL,后端服务器使用 HTTP)。
我已经看到 并且我 认为 这是我的问题:登录请求包含 returnurl
并且因为后端服务器正在使用 http, return 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):
我已经检查了上面提到的问题,也。他们都建议我应该在 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。如果我在上面添加的更改上放置一个断点,断点永远不会命中...不确定哪里出了问题?
我找到了使用 & this github issue 的解决方案:
负载均衡器将终止 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...
}
我正在使用 ASP.NET MVC,我正在使用 MS 内置模板以允许用户使用 Facebook 和 Google、外部 ID 登录。外部 ID 在我的生产环境中不起作用(在测试中起作用),我相信这是因为负载平衡器...(我在负载平衡器上卸载 SSL,后端服务器使用 HTTP)。
我已经看到 returnurl
并且因为后端服务器正在使用 http, return 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):
我已经检查了上面提到的问题,也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。如果我在上面添加的更改上放置一个断点,断点永远不会命中...不确定哪里出了问题?
我找到了使用
负载均衡器将终止 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...
}