C#Owin登录导致生产系统上的identity = null [英] C# Owin login results in identity=null on production system

查看:153
本文介绍了C#Owin登录导致生产系统上的identity = null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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:

  1. 阅读此github线程,了解当您使用Web cookie管理器(Correlation cookie,外部cookie和SystemWebCookieManager)时OWIN需要的一种解决方法:

https://github.com/aspnet/AspNetKatana/issues/331

  1. 也...(长版),当您在负载均衡器或某些代理后面进行工作时,该代理与流量逆向运行时,服务器可能会覆盖请求方案并最终调用facebook端点(/oauth)使用 http 协议(这就是为什么它在localhost或任何开发环境中都能正常工作的原因,因为它在前面没有LB的情况下运行).由于Facebook需要 https 来交换令牌并完成唱歌过程,因此您将收到?error = access_denied 响应(令人沮丧的+ _ +).
  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆