简体   繁体   English

Facebook .NET SDK:如何使用ASP.NET MVC 2进行身份验证

[英]Facebook .NET SDK: How to authenticate with ASP.NET MVC 2

I am trying to get the grip on the Facebook SDK and at the same time transitioning from ASP.NET forms to MVC (finally). 我试图掌握Facebook SDK,同时从ASP.NET表单过渡到MVC(最终)。 So please bear with me .. 所以,请忍受我..

I have created two controller actions: 我创建了两个控制器操作:

FBLogon is execetued when the user clicks on the FB login button on the form. 当用户单击表单上的FB登录按钮时,将执行FBLogon。 He is then redirected to the FB login page. 然后,他将被重定向到FB登录页面。

Afterwards he gets sent back to the FBAuthorize page, which is supposed to parse the returned url for the access token. 之后,他被发送回FBAuthorize页面,该页面应该解析返回的URL以获取访问令牌。 I get something like: 我得到类似的东西:

http://localhost:5000/account/FBAuthorize#access_token=199143326771791|827213759889396d5408fee6-100001815992604|BmYchAOMqSoZ2L0TYgCrtpoKP3M&expires_in=0 HTTP://本地主机:5000 /帐户/ FBAuthorize#=的access_token 199143326771791 | 827213759889396d5408fee6-100001815992604 | BmYchAOMqSoZ2L0TYgCrtpoKP3M&expires_in = 0

The problem I see, is that as the access_token is passed behind a #, asp.net cannot parse it on the server. 我看到的问题是,随着access_token在#后面传递,asp.net无法在服务器上解析它。 Am I doing something fundamentaly wrong? 我是从根本上做错了吗?

Code follows: 代码如下:

    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();
    }

Ok. 好。 The facebook docs say it quite clearly: Facebook文档说得很清楚:

Because the access token is passed in an URI fragment, only client-side code (such as JavaScript executing in the browser or desktop code hosting a web control) can retrieve the token. 由于访问令牌是在URI片段中传递的,因此只有客户端代码(例如在浏览器中执行的JavaScript或托管Web控件的桌面代码)才能检索该令牌。 App authentication is handled by verifying that the redirect_uri is in the same domain as the Site URL configured in the Developer App 通过验证redirect_uri与开发人员应用程序中配置的站点URL在同一个域中来处理应用程序身份验证

from http://developers.facebook.com/docs/authentication/ ---> Client-side Flow Section. http://developers.facebook.com/docs/authentication/ --->客户端流程部分。

So I'm sending the token back to my server to complete the authentication.. 因此,我将令牌发送回我的服务器以完成身份验证。

Update: 更新:

The sending back to the server I do using Javascript something like this: 发送回服务器我确实使用Java脚本,如下所示:

               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;
}

On the server then I have the following action. 然后在服务器上执行以下操作。 Not very nice but it works.. 不是很好,但是可以用。

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();
}

I am in the same spot you are at the moment. 我目前在同一地点。 We never get the Request.QueryString populated becasue of the "fragment" or # in the url. 我们永远不会因为URL中的“片段”或#而填充Request.QueryString。

Love to know if you solved this and how. 很想知道您是否解决了这个问题以及如何解决。

It does not look like the FacebookOAuthResult class was written to be used in web applications of any sort. 看起来FacebookOAuthResult类并非编写用于任何形式的Web应用程序。

you can change the response type in you scope paramas to be "code" then it will send back a code in the querystring in which you can swap for a token. 您可以将范围参数中的响应类型更改为“代码”,然后它将在查询字符串中发送回代码,您可以在其中交换令牌。

I found this post http://facebooksdk.codeplex.com/discussions/244568 on codeplex. 我在codeplex上找到了该帖子http://facebooksdk.codeplex.com/discussions/244568 I think this is what you need. 我认为这就是您所需要的。

Note that instead of using the client-side flow, you need to use the server-side flow. 请注意,您需要使用服务器端流,而不是使用客户端流。

This is what you should do 这是你应该做的

Create a login link for server-side flow. 为服务器端流创建一个登录链接。 After Authorization, facebook will return an url containing a code instead of a access token. 授权后,facebook将返回一个包含代码而不是访问令牌的URL。

Then you request for a token from facebook using the code. 然后,您使用代码从Facebook请求令牌。 this is my example 这是我的例子

    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();
    }

*There is bug when using IIS in localhost, see the original post for details (the redirect uri when asking for the token must be the same as the one used asking for the code) *在localhost中使用IIS时存在错误,请参阅原始文章以了解详细信息(请求令牌时的重定向uri必须与用于请求代码的重定向uri相同)

It is highly recommended to use IIS and not visual studio web server. 强烈建议使用IIS,而不是Visual Studio Web服务器。 There are many things that wont work in visual studio web server. 在Visual Studio Web服务器中,有很多东西无法使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM