C# Facebook.NETSDK:如何使用ASP.NETMVC2进行身份验证

C# Facebook.NETSDK:如何使用ASP.NETMVC2进行身份验证,c#,facebook,authentication,facebook-c#-sdk,C#,Facebook,Authentication,Facebook C# Sdk,我试图掌握Facebook SDK,同时从ASP.NET表单过渡到MVC(最终)。所以请容忍我 我创建了两个控制器操作: 当用户单击表单上的FB登录按钮时,将执行FBLogon。 然后他被重定向到FB登录页面 之后,他被发送回FBAuthorize页面,该页面应该解析访问令牌返回的url。我得到的结果是: 我看到的问题是,由于access_令牌是在一个#后面传递的,asp.net无法在服务器上解析它。我做错什么了吗 代码如下: public ActionResult FBLogon()

我试图掌握Facebook SDK,同时从ASP.NET表单过渡到MVC(最终)。所以请容忍我

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

当用户单击表单上的FB登录按钮时,将执行FBLogon。 然后他被重定向到FB登录页面

之后,他被发送回FBAuthorize页面,该页面应该解析访问令牌返回的url。我得到的结果是:

我看到的问题是,由于access_令牌是在一个#后面传递的,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();
    }
public ActionResult fbloon()
{
var settings=ConfigurationManager.GetSection(“facebookSettings”);
IFacebookApplication当前值=空;
如果(设置!=null)
{
当前=设置为iFaceBook应用程序;
if(current.AppId==“{app id}”| | current.AppSecret==“{app secret}”)
{
返回视图();
}
}
string[]extendedPermissions=new[]{“发布\流”,“脱机\访问”};
var oauth=new-facebookouthclient{ClientId=current.AppId,RedirectUri=new-Uri('http://localhost:5000/account/FBAuthorize") };
var参数=新字典
{
{“响应类型”,“令牌”},
{“显示”,“页面”}
};
if(extendedpowpermissions!=null&&extendedpowpermissions.Length>0)
{
var scope=新的StringBuilder();
Append(string.Join(“,”,extendedPermissions));
参数[“scope”]=scope.ToString();
}
var loginUrl=oauth.GetLoginUrl(参数);
返回重定向(loginUrl.ToString());
}
公共行动结果FBAuthorize()
{
FaceBookOuthResult结果;
if(facebookouthresult.TryParse(Request.Url,out result))
{
如果(结果。发布成功)
{
var accesstoken=result.accesstoken;
}
其他的
{
var errorDescription=result.errorDescription;
var errorReason=result.errorReason;
}
}
返回视图();
}

好的。facebook文档非常清楚地说:

因为访问令牌是传入的 URI片段,仅客户端代码 (例如在 承载web的浏览器或桌面代码 控件)可以检索令牌。应用程序 通过验证来处理身份验证 重定向uri是否处于相同的位置 域作为在中配置的站点URL 开发者应用程序

来自--->客户端流部分

因此,我将令牌发送回我的服务器以完成身份验证

更新:

我使用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;
}

我和你现在在同一个地方。 由于url中的“片段”或#,我们从未填充Request.QueryString

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

它看起来不像FacebookOAuthResult类是为在任何类型的web应用程序中使用而编写的

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

我在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();
    }
public ActionResult FBAuthorize()
{
FacebookOAuthClient cl=新的FacebookOAuthClient(FacebookContext.Current);
FacebookOAuthResult结果=null;
字符串url=Request.url.OriginalString;
//验证url中是否有代码
if(FacebookOAuthResult.TryParse(url,输出结果))
{
如果(结果。发布成功)
{                                       
字符串代码=result.code;
//这一行是必要的,直到他们修复了一个错误*见下面的详细信息
cl.RedirectUri=新的UriBuilder(“http://localhost:5000/account/FBAuthorize.Uri;
var参数=新字典();
//添加(“权限”、“脱机访问”);
Dictionary dict=(Dictionary)cl.ExchangeCodeForAccessToken(代码,新字典{{“重定向uri”,”http://localhost:5000/account/FBAuthorize" } });
对象标记=dict.Values.ElementAt(0);
TempData[“accessToken”]=Token.ToString();
返回重定向到操作(“ShowUser”);
}
其他的
{
var errorDescription=result.errorDescription;
}
}
其他的
{
//TODO:句柄错误
}             
返回视图();
}
*在localhost中使用IIS时存在错误,有关详细信息,请参阅原始帖子(请求令牌时的重定向uri必须与请求代码时使用的重定向uri相同)


强烈建议使用IIS而不是visual studio web server。在visual studio web server中有许多东西无法工作。

更新了我的答案。(顺便说一句,你的回答应该是评论)很棒的东西。坚持服务器端流程是关键。
    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();
    }