Facebook 是否在 2017 年 3 月更改了他们的应用程序开发人员 API?

Did Facebook change their App developers API on March 2017?

好吧,我是一个新手,正在尝试开发一个 web 应用程序,其用户将通过 Facebook 进行身份验证。我正在 MVC 4 .Net Framework. 开发应用程序,因为它的内部程序已经完成,所以我不需要做太多编码。我刚刚将 API IDSecret Key 放在范围

OAuthWebSecurity.RegisterFacebookClient(
                appId: "750397051803327",
                appSecret: "**************************");

这是我的申请 http://imgur.com/a/k4Vd0 我的应用程序完全正确地获得了用户的用户许可。 http://imgur.com/a/bqzj5 but after taking permission it is not providing the login state of the user by showing such exception http://imgur.com/a/h81Oh login failed. I debugged form the code end and I observed that it is sending isLoggedin as false http://imgur.com/a/UuLIe 因此我无法访问。

但是在我没有收到此类异常的 2 天前。我得到的数据很好。这是我以前数据的快照。 http://imgur.com/a/Bc49F

我再次需要该数据,但是如何?我的应用程序仪表板是否需要更改?可能我已经更改了应用程序仪表板中的某些内容。如果是那么特别是什么? 另一件让我感到困惑的事情是对产品的需求是什么?出于这个特殊原因,我需要产品中的任何东西来获取数据吗?如果是,那么我需要哪一个以及如何配置它以恢复我以前顺利获取数据的系统过程。

如果我从 PRODUCTS 添加 App Center 我将获得另外两个密钥,例如 Account Kit App SecretAccount Kit Client Token 我是否需要将这些密钥用于我请求的案件。对于此类登录批准,具体需要 ProductsPRODUCTS 根本不需要。我很困惑如何配置应用程序。

请建议我如何解决此问题以及如何配置我的应用程序 API。谢谢。

是的!!!! 我得到了自己问题的解决方案。根据 Facebook 开发人员的说法,bug report all Facebook log is not working from 28th March 2017. They also let us know through their developers Facebook group. The post link 就在这里。

According to one of the Developer teams had said we're finding that facebook authentication just stopped working (2pm EST) across multiple apps that we manage. apps haven't changed, apps haven't been suspended..... not sure where to report this since "status" is all good......

根据 我得到了我的解决方案。在 MVC4 每个人写下他们的 AppIDSecurityCode。由于 facebook GRAPH API 的更改,以前的链接已损坏。因此每个人都需要更改 RegisterFacebookClient 类。但是这个class在.Net库中是一个密封的class,所以任何人都不能扩展或覆盖它。结果我们需要使用wrapperclass。让我们考虑我的 Wrapper class 是 FacebookClientV2Dot3 因此我的 class 将是

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using DotNetOpenAuth.AspNet.Clients;
using Newtonsoft.Json;

public class FacebookClientV2Dot3 : OAuth2Client
{
    #region Constants and Fields

    /// <summary>
    /// The authorization endpoint.
    /// </summary>
    private const string AuthorizationEndpoint = "https://www.facebook.com/dialog/oauth";

    /// <summary>
    /// The token endpoint.
    /// </summary>
    private const string TokenEndpoint = "https://graph.facebook.com/oauth/access_token";

    /// <summary>
    /// The user info endpoint.
    /// </summary>
    private const string UserInfoEndpoint = "https://graph.facebook.com/me";

    /// <summary>
    /// The app id.
    /// </summary>
    private readonly string _appId;

    /// <summary>
    /// The app secret.
    /// </summary>
    private readonly string _appSecret;

    /// <summary>
    /// The requested scopes.
    /// </summary>
    private readonly string[] _requestedScopes;

    #endregion

    /// <summary>
    /// Creates a new Facebook OAuth2 client, requesting the default "email" scope.
    /// </summary>
    /// <param name="appId">The Facebook App Id</param>
    /// <param name="appSecret">The Facebook App Secret</param>
    public FacebookClient(string appId, string appSecret)
        : this(appId, appSecret, new[] { "email" }) { }

    /// <summary>
    /// Creates a new Facebook OAuth2 client.
    /// </summary>
    /// <param name="appId">The Facebook App Id</param>
    /// <param name="appSecret">The Facebook App Secret</param>
    /// <param name="requestedScopes">One or more requested scopes, passed without the base URI.</param>
    public FacebookClient(string appId, string appSecret, params string[] requestedScopes)
        : base("facebook")
    {
        if (string.IsNullOrWhiteSpace(appId))
            throw new ArgumentNullException("appId");

        if (string.IsNullOrWhiteSpace(appSecret))
            throw new ArgumentNullException("appSecret");

        if (requestedScopes == null)
            throw new ArgumentNullException("requestedScopes");

        if (requestedScopes.Length == 0)
            throw new ArgumentException("One or more scopes must be requested.", "requestedScopes");

        _appId = appId;
        _appSecret = appSecret;
        _requestedScopes = requestedScopes;
    }

    protected override Uri GetServiceLoginUrl(Uri returnUrl)
    {
        var state = string.IsNullOrEmpty(returnUrl.Query) ? string.Empty : returnUrl.Query.Substring(1);

        return BuildUri(AuthorizationEndpoint, new NameValueCollection
                {
                    { "client_id", _appId },
                    { "scope", string.Join(" ", _requestedScopes) },
                    { "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
                    { "state", state },
                });
    }

    protected override IDictionary<string, string> GetUserData(string accessToken)
    {
        var uri = BuildUri(UserInfoEndpoint, new NameValueCollection { { "access_token", accessToken } });

        var webRequest = (HttpWebRequest)WebRequest.Create(uri);

        using (var webResponse = webRequest.GetResponse())
        using (var stream = webResponse.GetResponseStream())
        {
            if (stream == null)
                return null;

            using (var textReader = new StreamReader(stream))
            {
                var json = textReader.ReadToEnd();
                var extraData = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
                var data = extraData.ToDictionary(x => x.Key, x => x.Value.ToString());

                data.Add("picture", string.Format("https://graph.facebook.com/{0}/picture", data["id"]));

                return data;
            }
        }
    }

    protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
    {
        var uri = BuildUri(TokenEndpoint, new NameValueCollection
                {
                    { "code", authorizationCode },
                    { "client_id", _appId },
                    { "client_secret", _appSecret },
                    { "redirect_uri", returnUrl.GetLeftPart(UriPartial.Path) },
                });

        var webRequest = (HttpWebRequest)WebRequest.Create(uri);
        string accessToken = null;
        HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();

        // handle response from FB 
        // this will not be a url with params like the first request to get the 'code'
        Encoding rEncoding = Encoding.GetEncoding(response.CharacterSet);

        using (StreamReader sr = new StreamReader(response.GetResponseStream(), rEncoding))
        {
            var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
            var jsonObject = serializer.DeserializeObject(sr.ReadToEnd());
            var jConvert = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(jsonObject));

            Dictionary<string, object> desirializedJsonObject = JsonConvert.DeserializeObject<Dictionary<string, object>>(jConvert.ToString());
            accessToken = desirializedJsonObject["access_token"].ToString();
        }
        return accessToken;
    }

    private static Uri BuildUri(string baseUri, NameValueCollection queryParameters)
    {
        var keyValuePairs = queryParameters.AllKeys.Select(k => HttpUtility.UrlEncode(k) + "=" + HttpUtility.UrlEncode(queryParameters[k]));
        var qs = String.Join("&", keyValuePairs);

        var builder = new UriBuilder(baseUri) { Query = qs };
        return builder.Uri;
    }

    /// <summary>
    /// Facebook works best when return data be packed into a "state" parameter.
    /// This should be called before verifying the request, so that the url is rewritten to support this.
    /// </summary>
    public static void RewriteRequest()
    {
        var ctx = HttpContext.Current;

        var stateString = HttpUtility.UrlDecode(ctx.Request.QueryString["state"]);
        if (stateString == null || !stateString.Contains("__provider__=facebook"))
            return;

        var q = HttpUtility.ParseQueryString(stateString);
        q.Add(ctx.Request.QueryString);
        q.Remove("state");

        ctx.RewritePath(ctx.Request.Path + "?" + q);
    }
}

看这里,我已经用较新版本的链接替换了所有 API 链接。

现在你需要修改你的

AuthConfig

只需使用包装器class

OAuthWebSecurity.RegisterClient(new FacebookClientV2Dot3("AppID", "HassedPassword"));

然后一切成功。您的 Facebook 登录将恢复到以前的状态。

然而,您可能会遇到关于这个新 API 而不是以前的 API 的新问题,问题是 IP Whitelisting。像这样image。希望你只需要这个。编码愉快。