c# - Facebook 的 OAuthWebSecurity 未按预期使用电子邮件权限

标签 c# asp.net-mvc facebook oauth

使用新的 OAuthWebSecurity 进行 Facebook 身份验证,我在我的 Facebook 应用程序中添加了电子邮件权限。现在,正如我所见,我需要定义一个范围,以便能够在结果中实际获取电子邮件。到目前为止,在没有范围的情况下,我没有收到用户的电子邮件,也不知道为什么,因为我看不到在哪里定义“范围”。

这只是 ASP.NET MVC 的一小部分4个默认的authenticationcontrollers外部登录。

最佳答案

首先,extraData参数没有传递给facebook。它仅供内部使用。请参阅以下链接,了解如何在您的网站上使用这些数据:

http://blogs.msdn.com/b/pranav_rastogi/archive/2012/08/24/customizing-the-login-ui-when-using-oauth-openid.aspx

现在,到肉:

OAuthWebSecurity中除了RegisterFacebookClientRegisterYahooClient等方法外,还有一个泛型方法RegisterClient。这是我们将用于此解决方案的方法。

这个想法源于以下提供的代码: http://mvc4beginner.com/Sample-Code/Facebook-Twitter/MVC-4-oAuth-Facebook-Login-EMail-Problem-Solved.html

但是,我们不会使用该解决方案提供的 hacky 方法。相反,我们将创建一个名为 FacebookScopedClient 的新类,它将实现 IAuthenticationClient。然后我们将简单地注册类使用:

OAuthWebSecurity.RegisterClient(new FacebookScopedClient("your_app_id", "your_app_secret"), "Facebook", null);

在 AuthConfig.cs 中

类的代码是:

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

    public class FacebookScopedClient : IAuthenticationClient
        {
            private string appId;
            private string appSecret;

            private const string baseUrl = "https://www.facebook.com/dialog/oauth?client_id=";
            public const string graphApiToken = "https://graph.facebook.com/oauth/access_token?";
            public const string graphApiMe = "https://graph.facebook.com/me?";


            private static string GetHTML(string URL)
            {
                string connectionString = URL;

                try
                {
                    System.Net.HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(connectionString);
                    myRequest.Credentials = CredentialCache.DefaultCredentials;
                    //// Get the response
                    WebResponse webResponse = myRequest.GetResponse();
                    Stream respStream = webResponse.GetResponseStream();
                    ////
                    StreamReader ioStream = new StreamReader(respStream);
                    string pageContent = ioStream.ReadToEnd();
                    //// Close streams
                    ioStream.Close();
                    respStream.Close();
                    return pageContent;
                }
                catch (Exception)
                {
                }
                return null;
            }

            private  IDictionary<string, string> GetUserData(string accessCode, string redirectURI)
            {

                string token = GetHTML(graphApiToken + "client_id=" + appId + "&redirect_uri=" + HttpUtility.UrlEncode(redirectURI) + "&client_secret=" + appSecret + "&code=" + accessCode);
                if (token == null || token == "")
                {
                    return null;
                }
                string data = GetHTML(graphApiMe + "fields=id,name,email,gender,link&access_token=" + token.Substring("access_token=", "&"));

                // this dictionary must contains
                Dictionary<string, string> userData = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
                return userData;
            }

            public FacebookScopedClient(string appId, string appSecret)
            {
                this.appId = appId;
                this.appSecret = appSecret;
            }

            public string ProviderName
            {
                get { return "Facebook"; }
            }

            public void RequestAuthentication(System.Web.HttpContextBase context, Uri returnUrl)
            {
                string url = baseUrl + appId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=email";
                context.Response.Redirect(url);
            }

            public AuthenticationResult VerifyAuthentication(System.Web.HttpContextBase context)
            {
                string code = context.Request.QueryString["code"];

                string rawUrl = context.Request.Url.OriginalString;
                //From this we need to remove code portion
                rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", "");

                IDictionary<string, string> userData = GetUserData(code, rawUrl);

                if (userData == null)
                    return new AuthenticationResult(false, ProviderName, null, null, null);

                string id = userData["id"];
                string username = userData["email"];
                userData.Remove("id");
                userData.Remove("email");

                AuthenticationResult result = new AuthenticationResult(true, ProviderName, id, username, userData);
                return result;
            }
        }

现在在

public ActionResult ExternalLoginCallback(string returnUrl)

AccountController 中的方法,result.ExtraData 应该有电子邮件。

编辑:我在这篇文章中遗漏了一些代码。我在下面添加它:

public static class String
    {
        public static string Substring(this string str, string StartString, string EndString)
        {
            if (str.Contains(StartString))
            {
                int iStart = str.IndexOf(StartString) + StartString.Length;
                int iEnd = str.IndexOf(EndString, iStart);
                return str.Substring(iStart, (iEnd - iStart));
            }
            return null;
        }
    }

干杯!

关于c# - Facebook 的 OAuthWebSecurity 未按预期使用电子邮件权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12610402/

相关文章:

c# - 以编程方式启用辅助监视器

javascript - 从服务器到客户端的 SignalR 消息重复

PHP fatal error : Uncaught CurlException: 28 and 35 on Facebook apps

facebook - 如何在数据库中存储 Facebook 个人资料图片?

c# - 在单独的实体项目中实现 EF6 个人用户帐户

javascript - 单击按钮时如何退出 native 应用程序?

c# - 将 XML 绑定(bind)到 wpf 数据网格

c# - 如何在 Entity Framework 中一次调用使用 UNION(concat/union)?

c# - 计算百分位数以去除异常值的快速算法

javascript - 在显示微调器的同时对服务器端代码进行 ajax 调用时,IE 浏览器会阻止 UI