C#Owin登录导致生产系统上的identity = null [英] C# Owin login results in identity=null on production system
问题描述
我有一个asp.net MVC 5 Web项目,该项目在我的开发系统上运行良好.但是由于某种原因,一旦我在生产系统上部署了该解决方案,使用Microsoft Owin和Facebook的登录就会停止.
I've got an asp.net MVC 5 web project which is running fine on my development system. But for some reason, the login using Microsoft Owin with Facebook stops working as soon as I deploy the solution on my production system.
回调总是检索.... error = access_denied作为参数,我将其追溯到owin为我的身份返回null的事实.有什么线索吗?
The callback always retrieves ....error=access_denied as parameter and I tracked it back to the fact that owin returns null for my identity. Any clue whats going on here?
更新
我在Owin代码中实现了log4net,并且能够进行更深入的研究:
I implemented log4net in my Owin code and was able to dive deeper:
Response status code does not indicate success: 400 (Bad Request).
Stack trace:
at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
at Microsoft.Owin.Security.Facebook.FacebookAuthenticationHandler<AuthenticateCoreAsync>d__0.MoveNext()
请不要因为我已经修改了Facebook应用程序以匹配生产网址,响应等.
Please not that I have already modified the facebook app to match the production urls, responses etc.
private void ConfigureAuth(IAppBuilder app)
{
var cookieOptions = new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
};
app.UseCookieAuthentication(cookieOptions);
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); // Passive
app.SetDefaultSignInAsAuthenticationType(cookieOptions.AuthenticationType);
app.UseFacebookAuthentication(new FacebookAuthenticationOptions
{
AppSecret = ConfigurationManager.AppSettings["FacebookAppSecret"],
AppId = ConfigurationManager.AppSettings["FacebookAppId"],
Provider = new FacebookAuthenticationProvider()
{
OnAuthenticated = (context) =>
{
context.Identity.AddClaim(new Claim(
IdentityUtility.ExtendedClaimTypes.IdentityProvider,
"Facebook"));
return Task.FromResult(0);
},
OnReturnEndpoint = (context) =>
{
if(context.Identity == null)
throw new Exception(context.Response.StatusCode.ToString());
return Task.FromResult(0);
}
}
});
}
关于,马丁
推荐答案
也许您已经解决了!无论如何...我会发布此答案,以防万一其他失去的灵魂(?)来到这里寻找其他替代方法或解决方法.
Maybe you already solved it! Anyway... I'll post this answer just in case that any other lost soul (?) comes here looking for some other alternatives or workarounds.
我为类似的问题而奋斗了几天!为了节省时间,我建议您首先尝试以下方法:
I was fighting with a similar issue for a couple of days! In order to save time I would recommend you to try the following first:
- 阅读此github线程,了解当您使用Web cookie管理器(Correlation cookie,外部cookie和SystemWebCookieManager)时OWIN需要的一种解决方法:
https://github.com/aspnet/AspNetKatana/issues/331
- 也...(长版),当您在负载均衡器或某些代理后面进行工作时,该代理与流量逆向运行时,服务器可能会覆盖请求方案并最终调用facebook端点(/oauth)使用 http 协议(这就是为什么它在localhost或任何开发环境中都能正常工作的原因,因为它在前面没有LB的情况下运行).由于Facebook需要 https 来交换令牌并完成唱歌过程,因此您将收到?error = access_denied 响应(令人沮丧的+ _ +).
- Also... (long version) when you're working behind a load balancer or some proxy that makes a reverse with the traffic your server could be doing an overwrite over the requests schemes and finally calling facebook endpoints (/oauth) using http protocol (That's why it works fine on localhost or any development environment, because it runs without a LB at front). Since Facebook requires https in order to exchange tokens and complete the sing in process you will receive an ?error=access_denied response (it's so frustrating +_+).
(简短版):您可以断言某些请求(在反向之前)使用https,然后覆盖context.request属性以将其还原.您可以使用中间件(OWIN)来检查原始请求中的"x-forwarded-proto"请求标头.
(short version): You can assert that some request (before the reverse) was using https and overwrite the context.request attribute to restore it. And you can do it using a middleware (OWIN) to check the 'x-forwarded-proto' request header from the original request.
只需在将 声明为默认登录身份验证类型(SetDefaultSignInAsAuthenticationType)之前,先使用OWIN中间件.这里的顺序很重要,因为中间件可以用作管道!(更多信息在这里-> https://docs.microsoft.com/zh-cn/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline a>)
Just apply the OWIN middleware before declaring external cookies as default sign-in authentication type (SetDefaultSignInAsAuthenticationType). The order is important here because the middleware works as a pipeline! (more info here -> https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline)
示例代码段:
// This is the middleware fixing the request scheme
app.Use((context, next) => {
if (context.Request.Headers["x-forwarded-proto"] == "https")
{
context.Request.Scheme = "https";
}
return next();
});
// The following lines are related with the step 1 issue!
app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ExternalCookie);
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
AuthenticationMode = AuthenticationMode.Passive,
CookieName = CookiePrefix + DefaultAuthenticationTypes.ExternalCookie,
ExpireTimeSpan = TimeSpan.FromMinutes(5),
CookieManager = new SystemWebCookieManager()
});
...
有关x-forwarded-proto标头的更多信息在这里-> https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/X-Forwarded-Proto .这里的关键点是:
More info about x-forwarded-proto header here -> https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto . The key point here is:
X-Forwarded-Proto(XFP)标头是一种事实上的标准标头,用于标识客户端用于连接的协议(HTTP或HTTPS)到您的代理或负载平衡器.
The X-Forwarded-Proto (XFP) header is a de-facto standard header for identifying the protocol (HTTP or HTTPS) that a client used to connect to your proxy or load balancer.
这篇关于C#Owin登录导致生产系统上的identity = null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!