【问题标题】:Facebook .NET SDK: How to authenticate with ASP.NET MVC 2Facebook .NET SDK:如何使用 ASP.NET MVC 2 进行身份验证
【发布时间】:2011-02-22 07:30:02
【问题描述】:

我正在尝试掌握 Facebook SDK,同时从 ASP.NET 表单过渡到 MVC(最终)。所以请多多包涵..

我创建了两个控制器动作:

当用户单击表单上的 FB 登录按钮时,将执行 FBLogon。 然后他被重定向到 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();
    }

【问题讨论】:

    标签: c# facebook authentication facebook-c#-sdk


    【解决方案1】:

    好的。 facebook 文档说得很清楚:

    因为访问令牌传入 一个 URI 片段,只有客户端代码 (例如 JavaScript 在 托管网络的浏览器或桌面代码 control) 可以检索令牌。应用程序 身份验证通过验证来处理 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();
    }
    

    【讨论】:

      【解决方案2】:

      我在 codeplex 上找到了这个帖子 http://facebooksdk.codeplex.com/discussions/244568。我想这就是你需要的。

      请注意,您需要使用服务器端流程,而不是使用客户端流程。

      这是你应该做的

      为服务器端流程创建登录链接。授权后,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();
          }
      

      *在localhost中使用IIS时有bug,详情见原帖(索取token时的redirect uri必须与索取code时使用的相同)

      强烈建议使用 IIS 而不是 Visual Studio Web 服务器。有很多东西在 Visual Studio Web 服务器中不起作用。

      【讨论】:

      • 好东西。坚持服务器端流程是关键。
      【解决方案3】:

      我现在和你在同一个地方。 由于 url 中的“片段”或 #,我们永远不会得到填充的 Request.QueryString。

      很想知道你是否解决了这个问题以及如何解决。

      看起来 FacebookOAuthResult 类并不是为了在任何类型的 Web 应用程序中使用而编写的。

      您可以将范围参数中的响应类型更改为“代码”,然后它将在查询字符串中发回一个代码,您可以在其中交换令牌。

      【讨论】:

      • 更新了我的答案。 (顺便说一句,您的回答应该是评论)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-19
      • 2017-12-10
      相关资源
      最近更新 更多