FacebookMiddleware在外部登录中的作用是什么?

时间:2017-03-08 12:04:38

标签: asp.net-core asp.net-identity

我在我的应用程序中使用ASP.NET Core Identity,我启用了外部登录(到Facebook);我的问题是,在用户点击登录页面中的Facebook按钮后,FacebookMiddleware的角色是什么,重定向到Facebook登录页面,单击确定,然后通过Facebook重定向回到ExternalLoginCallback方法...其中是所有这个计划中的FacebookMiddleware及其功能如何?

2 个答案:

答案 0 :(得分:0)

顾名思义,FacebookMiddleware是使用Facebook验证用户身份的组件。

当您调用UseFacebookAuthentication调用时,它基本上连接了FacebookMiddleware。

FacebookMiddleware内部使用FacebookHandler

没有比代码本身更好的解释,所以这里是FacebookHandler的代码

 internal class FacebookHandler : OAuthHandler<FacebookOptions>
        {
            public FacebookHandler(HttpClient httpClient) : base(httpClient)
            {
            }

            protected override async Task<AuthenticationTicket>   CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
            {
                string text = QueryHelpers.AddQueryString(this.get_Options().get_UserInformationEndpoint(), "access_token", tokens.get_AccessToken());
                if (this.get_Options().SendAppSecretProof)
                {
                    text = QueryHelpers.AddQueryString(text, "appsecret_proof", this.GenerateAppSecretProof(tokens.get_AccessToken()));
                }
                if (this.get_Options().Fields.get_Count() > 0)
                {
                    text = QueryHelpers.AddQueryString(text, "fields", string.Join(",", this.get_Options().Fields));
                }
                HttpResponseMessage httpResponseMessage = await this.get_Backchannel().GetAsync(text, this.get_Context().get_RequestAborted());
                if (!httpResponseMessage.get_IsSuccessStatusCode())
                {
                    throw new HttpRequestException(string.Format("Failed to retrieve Facebook user information ({0}) Please check if the authentication information is correct and the corresponding Facebook Graph API is enabled.", httpResponseMessage.get_StatusCode()));
                }
                JObject jObject = JObject.Parse(await httpResponseMessage.get_Content().ReadAsStringAsync());
                AuthenticationTicket authenticationTicket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, this.get_Options().get_AuthenticationScheme());
                OAuthCreatingTicketContext oAuthCreatingTicketContext = new OAuthCreatingTicketContext(authenticationTicket, this.get_Context(), this.get_Options(), this.get_Backchannel(), tokens, jObject);
                string id = FacebookHelper.GetId(jObject);
                if (!string.IsNullOrEmpty(id))
                {
                    identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", id, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
                }
                string ageRangeMin = FacebookHelper.GetAgeRangeMin(jObject);
                if (!string.IsNullOrEmpty(ageRangeMin))
                {
                    identity.AddClaim(new  Claim("urn:facebook:age_range_min", ageRangeMin, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
                }
                string ageRangeMax = FacebookHelper.GetAgeRangeMax(jObject);
                if (!string.IsNullOrEmpty(ageRangeMax))
                {
                    identity.AddClaim(new Claim("urn:facebook:age_range_max", ageRangeMax, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
                }
                string birthday = FacebookHelper.GetBirthday(jObject);
                if (!string.IsNullOrEmpty(birthday))
                {
                    identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth", birthday, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
                }
                string email = FacebookHelper.GetEmail(jObject);
            if (!string.IsNullOrEmpty(email))
            {
                identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", email, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            string firstName = FacebookHelper.GetFirstName(jObject);
            if (!string.IsNullOrEmpty(firstName))
            {
                identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", firstName, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            string gender = FacebookHelper.GetGender(jObject);
            if (!string.IsNullOrEmpty(gender))
            {
                identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender", gender, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            string lastName = FacebookHelper.GetLastName(jObject);
            if (!string.IsNullOrEmpty(lastName))
            {
                identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname", lastName, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            string link = FacebookHelper.GetLink(jObject);
            if (!string.IsNullOrEmpty(link))
            {
                identity.AddClaim(new Claim("urn:facebook:link", link, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            string location = FacebookHelper.GetLocation(jObject);
            if (!string.IsNullOrEmpty(location))
            {
                identity.AddClaim(new Claim("urn:facebook:location", location, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            string locale = FacebookHelper.GetLocale(jObject);
            if (!string.IsNullOrEmpty(locale))
            {
                identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality", locale, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            string middleName = FacebookHelper.GetMiddleName(jObject);
            if (!string.IsNullOrEmpty(middleName))
            {
                identity.AddClaim(new Claim("urn:facebook:middle_name", middleName, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            string name = FacebookHelper.GetName(jObject);
            if (!string.IsNullOrEmpty(name))
            {
                identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", name, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            string timeZone = FacebookHelper.GetTimeZone(jObject);
            if (!string.IsNullOrEmpty(timeZone))
            {
                identity.AddClaim(new Claim("urn:facebook:timezone", timeZone, "http://www.w3.org/2001/XMLSchema#string", this.get_Options().get_ClaimsIssuer()));
            }
            await this.get_Options().get_Events().CreatingTicket(oAuthCreatingTicketContext);
            return oAuthCreatingTicketContext.get_Ticket();
        }

        private string GenerateAppSecretProof(string accessToken)
        {
            string result;
            using (HMACSHA256 hMACSHA = new HMACSHA256(Encoding.get_ASCII().GetBytes(base.get_Options().AppSecret)))
            {
                byte[] array = hMACSHA.ComputeHash(Encoding.get_ASCII().GetBytes(accessToken));
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < array.Length; i++)
                {
                    stringBuilder.Append(array[i].ToString("x2", CultureInfo.get_InvariantCulture()));
                }
                result = stringBuilder.ToString();
            }
            return result;
        }

        protected override string FormatScope()
        {
            return string.Join(",", base.get_Options().get_Scope());
        }
    }
}

答案 1 :(得分:0)

以防有人遇到同样的问题:从中间件的这段代码中抛出错误:

var response = Backchannel.GetAsync(endpoint).Result; if (!response.IsSuccessStatusCode) { throw new HttpRequestException($"Failed to retrieve Facebook user information ({response.StatusCode}) Please check if the authentication information is correct and the corresponding Facebook Graph API is enabled."); }

简而言之,开发人员决定,如果状态代码不是成功的,只需抛出一般错误消息。另外要知道真正的错误,你可以使用Fiddler等工具来捕获Facebook的回复,在我看来如下所示:

  

{&#34;错误&#34;:{&#34;消息&#34;:&#34;语法错误\&#34;字符串的预期结束而不是\&#34 ;; \&#34 ; \&#34;在字符5:电子邮件; first_name; last_name&#34;,&#34;键入&#34;:&#34; OAuthException&#34;,&#34; code&#34;:2500,&#34; fbtrace_id&#34; :&#34; XXXXXXXX&#34;}}