3

OAuth と Facebook に問題があります。MVC4 標準の OAuth ログインを使用しています。ローカルでは問題が発生していませんが、サーバーではこれが問題であることが証明されています。

次の URL をブラウザに貼り付けると、正常に動作します。

http://localhost:46260/Account/ExternalLoginCallback?ReturnUrl=%2FDashboard&__provider__=FacebookPro&__sid__=1234somesid456  // this is autogenerated

Facebook のアプリの URL を現在のドメインに変更してこの URL を貼り付けると、失敗したログイン ページにリダイレクトされます。

http://freersvp.mytakeawaysite.com:80/Account/ExternalLoginCallback?ReturnUrl=%2FDashboard&__provider__=Facebook+Pro&__sid__=1234someid456  // note this is autogenerated

: 上記の 2 つの URL はリダイレクト URI です。

以下の URL は要求されたものであり、例外を引き起こしています。

URL

https://graph.facebook.com/oauth/access_token?client_id=52*********37&redirect_uri=http%3a%2f%2ffreersvp.mytakeawaysite.com%3a80%2fAccount%2fExternalLoginCallback%3fReturnUrl%3d%252FDashboard%26__provider__%3dFacebook%2bPro%26__sid__%3d3c92eb7e84304afc931ef0ea7b62f56a&client_secret=2123***********4256&code=AQAQIJsj-ondldllVYKdpxJaZouqrlg9sjTcfUxyWhAw8MXbD2DvsOSujg2m7E3s3cvNusCI0ZZoJAuGgu_FLkPyjYMQAkTWDVyHTcAoJD-tezyXgn0vhoFzX3FmuRBHYpyJEM-dk0KgF5ugsTHo9yGjBjrcfMDUGu9IxkKQ36k3gMrwocM1_l5t342Q2kIOHdt8pPcyrs--NzgNyZv48vSq7jkZwuQ95xRjUHG5J-ptcgq0l2BlqjzHDDuvIFH23lpMWHzzqdejdj5ejukz7t_Fnhx-mrpVdcRYhP3JeZ2UOTjAyKQmUB3rInooECcjq4c

例外

  {
       "error": {
          "message": "Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request",
          "type": "OAuthException",
          "code": 100
       }
    }

以下のコードの関数では、string tokennull が返されます。GetUserData

私は FacebookScopedClient を使用しています:

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

    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 ex)
        {
        }
        return null;
    }

    private IDictionary<string, string> GetUserData(string accessCode, string redirectURI)
    {
        SessionControl ctl = new SessionControl();
        ctl.SaveParam("redirecturi", redirectURI, -3);
        ctl.Dispose();
        string token = GetHTML(graphApiToken + "client_id=" + appId + "&redirect_uri=" + HttpUtility.UrlEncode(redirectURI) + "&client_secret=" + appSecret + "&code=" + accessCode);

        if(token == null || token == "")
        {

            return null;
        }
        string access_token = token.Substring(token.IndexOf("access_token="), token.IndexOf("&"));
        string data = GetHTML(graphApiMe + "fields=id,name,email,username,gender,link&" + access_token);

        try
        {


        }
        catch { }
        // this dictionary must contains
        Dictionary<string, string> userData = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
        userData.Add("accesstoken", access_token);

        try
        {
            userData.Add("id", userData["id"]);
        }
        catch { }
        return userData;
    }

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

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

    public void RequestAuthentication(System.Web.HttpContextBase context, Uri returnUrl)
    {
        string url = baseUrl + appId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=" + scope;
        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"];

        if(username == null || username == "")
        {
            username = userData["username"];
        }
        //userData.Remove("id");
        userData.Remove("username");

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

3 に答える 3

3

URLデコーダーを介してエラーの原因となっている投稿されたURLを実行した後、何らかの理由で、URLだけでなくクエリ文字列全体をエンコードするURLに問題があります。

その URL には、URL エンコードされた %26 アイテムの束があり、それがエラーをスローしていることに気付くでしょう。Facebook パーサーは & の代わりに %26 を認識し、それを 1 つのパラメーターとして扱っています。

& は、ページに送信するときに URL クエリ文字列パラメーターを区切ります。完全なコードがなければ、どこを見ればよいかわかりませんが、コードのどこかでクエリ文字列全体を完全にエンコードし、そのコードを見つけて埋め込まれた URL のみをエンコードする必要があります。

物事を読んだ後、この理論を試してみてください。

あなたのコードはFacebookからこのようなものを受け取り、URLがエンコードされ、システムがそれを再エンコードしていると思います。受信したものをすべて取り、最初に URL デコードし、操作してから、必要に応じて再エンコードしてみてください。

お役に立てれば

于 2013-09-20T19:32:50.773 に答える
0

Facebook アプリ内でサンドボックス モードをオフにして試してください。

于 2013-09-19T07:39:16.983 に答える
-1

URL のクエリ文字列に注目して、Stackoverflow から回答を見つけました。問題が解決するかどうかを確認してください: https://stackoverflow.com/a/16699058/2005136

スティーブ S は応答として投稿しました:

「私たちの場合、私たちは異常なことをしていました (したがって、これはあなたのケースには関係ないかもしれません)。私たちの redirect_uri は、別の URL がエンコードされたパス要素として埋め込まれた URL でした。URL 内の URL、二重にエンコードされたときにFB に渡され、Facebook API サーバーで問題を引き起こし始めていました。

ネストされた URL のエンコーディングを % エンコーディングではなく長い 16 進数に変更することでこれを解決したため、すべての Facebook サーバーはパス内に何らかの 16 進数を含む単純な redirect_uri を認識し、通常の URL エンコーディング/デコーディングの影響を受けません。」

于 2013-09-16T19:36:01.070 に答える