Facebook .NET SDK: как пройти аутентификацию с помощью ASP.NET MVC 2 - PullRequest
2 голосов
/ 22 февраля 2011

Я пытаюсь получить контроль над SDK Facebook и в то же время переходить от форм ASP.NET к MVC (наконец).Поэтому, пожалуйста, потерпите меня ..

Я создал два действия контроллера:

FBLogon завершается, когда пользователь нажимает кнопку входа FB в форме.Затем он перенаправляется на страницу входа в FB.

После этого его отправляют обратно на страницу FBAuthorize, которая должна проанализировать возвращенный URL-адрес для маркера доступа.Я получаю что-то вроде:

http://localhost:5000/account/FBAuthorize#access_token=199143326771791|827213759889396d5408fee6-100001815992604|BmYchAOMqSoZ2L0TYgCrtpoKP3M&expires_in=0

Проблема, которую я вижу, состоит в том, что, поскольку access_token передается за #, asp.net не может проанализировать его на сервере.Я делаю что-то в корне неправильно?

Код следующий:

    public ActionResult FBLogon()
    {
        var settings = ConfigurationManager.GetSection("facebookSettings");
        IFacebookApplication current = null;

        if (settings != null)
        {
            current = settings as IFacebookApplication;
            if (current.AppId == "{app id}" || current.AppSecret == "{app secret}")
            {
                return View();
            }
        }

        string[] extendedPermissions = new[] { "publish_stream", "offline_access" };
        var oauth = new FacebookOAuthClient { ClientId = current.AppId, RedirectUri = new Uri("http://localhost:5000/account/FBAuthorize") };
        var parameters = new Dictionary<string, object>
                {
                    { "response_type", "token" },
                    { "display", "page" }
                };

        if (extendedPermissions != null && extendedPermissions.Length > 0)
        {
            var scope = new StringBuilder();
            scope.Append(string.Join(",", extendedPermissions));
            parameters["scope"] = scope.ToString();
        }


        var loginUrl = oauth.GetLoginUrl(parameters);
        return  Redirect(loginUrl.ToString());
    }


    public ActionResult FBAuthorize()
    {

        FacebookOAuthResult result;
        if (FacebookOAuthResult.TryParse(Request.Url, out result))
        {
            if (result.IsSuccess)
            {
                var accesstoken = result.AccessToken;
            }
            else
            {
                var errorDescription = result.ErrorDescription;
                var errorReason = result.ErrorReason;
            }
        }
        return View();
    }

Ответы [ 3 ]

3 голосов
/ 22 февраля 2011

Хорошо. Документы в фейсбуке говорят об этом довольно четко:

Поскольку маркер доступа передается в фрагмент URI, только код на стороне клиента (например, выполнение JavaScript в код браузера или десктопа, размещающий веб контроль) может получить токен. Приложение аутентификация обрабатывается путем проверки что redirect_uri находится в том же домен в качестве URL сайта, настроенного в приложение для разработчиков

из http://developers.facebook.com/docs/authentication/ ---> Секция потока на стороне клиента.

Итак, я отправляю токен обратно на сервер для завершения аутентификации.

Обновление:

Отправка обратно на сервер, я делаю с использованием Javascript примерно так:

               var appId = "<%: Facebook.FacebookContext.Current.AppId %>";

                if (window.location.hash.length > 0) {
                    accessToken = window.location.hash.substring(1);
                    var url = window.location.href.replace(/#/, '?');
                    window.location = url;
}

На сервере у меня следующее действие. Не очень хорошо, но это работает ..

public ActionResult FBAuthorize()
{

    FacebookOAuthResult result  = null;


    string url = Request.Url.OriginalString;
    /// hack to make FacebookOuthResult accept the token..
    url = url.Replace("FBAuthorize?", "FBAuthorize#");

    if (FacebookOAuthResult.TryParse(url, out result))
    {
        if (result.IsSuccess)
        {

            string[] extendedPermissions = new[] { "user_about_me", "offline_access" };

            var fb = new FacebookClient(result.AccessToken);

            dynamic resultGet = fb.Get("/me");
            var name = resultGet.name;

            RegisterModel rm = new Models.RegisterModel();
            rm.UserName = name;
            rm.Password = "something";
            rm.Email = "somethig";
            rm.ConfirmPassword = "23213";
            //Label1.Text = name;

            //Response.Write(name);
            //return RedirectToAction("register", "Account", rm);
            ViewData["Register"] = rm;
            return RedirectToAction("Register");

        }
        else
        {
            var errorDescription = result.ErrorDescription;
            var errorReason = result.ErrorReason;
        }
    }
    return View();
}
1 голос
/ 25 февраля 2011

Я нашел этот пост http://facebooksdk.codeplex.com/discussions/244568 на codeplex. Я думаю, что это то, что вам нужно.

Обратите внимание, что вместо использования потока на стороне клиента необходимо использовать поток на стороне сервера.

Это то, что вы должны сделать

Создать ссылку для входа в систему на стороне сервера. После авторизации Facebook вернет URL-адрес, содержащий код вместо токена доступа.

Затем вы запрашиваете токен из Facebook, используя код. это мой пример

    public ActionResult FBAuthorize()
    {
        FacebookOAuthClient cl = new FacebookOAuthClient(FacebookContext.Current);
        FacebookOAuthResult result = null; 
        string url = Request.Url.OriginalString;

        // verify that there is a code in the url
        if (FacebookOAuthResult.TryParse(url, out result))
        {
            if (result.IsSuccess)
            {                                       
                string code = result.Code;

                // this line is necessary till they fix a bug *see details below
                cl.RedirectUri = new UriBuilder("http://localhost:5000/account/FBAuthorize").Uri;

                var parameters = new Dictionary<string, object>();

                //parameters.Add("permissions", "offline_access");

                Dictionary<String, Object> dict = (Dictionary<String, Object>)cl.ExchangeCodeForAccessToken(code, new Dictionary<string, object> { { "redirect_uri", "http://localhost:5000/account/FBAuthorize" } });


                Object Token = dict.Values.ElementAt(0);

                TempData["accessToken"] = Token.ToString();

                return RedirectToAction ("ShowUser");
            }
            else
            {
                var errorDescription = result.ErrorDescription;
            }
        }
        else 
        {
            // TODO: handle error
        }             
        return View();
    }

* Ошибка при использовании IIS в localhost, подробности см. В исходном посте (uri перенаправления при запросе токена должно совпадать с используемым при запросе кода)

Настоятельно рекомендуется использовать IIS, а не веб-сервер visual studio. Есть много вещей, которые не будут работать на веб-сервере visual studio.

1 голос
/ 24 февраля 2011

Я нахожусь в том же месте, что и вы в данный момент.Мы никогда не получим заполненный Request.QueryString из-за «фрагмента» или # в URL.

Нам нравится знать, если вы решили это и как.

Это не похоже на класс FacebookOAuthResultбыл написан для использования в веб-приложениях любого типа.

вы можете изменить тип ответа в параметрах своей области на «код», после чего он отправит обратно код в строке запроса, в которой вы можете поменяться местами длямаркер.

...