DotNetOpenAuth CTP - Facebook的坏请求 [英] DotNetOpenAuth CTP - Facebook bad request

查看:184
本文介绍了DotNetOpenAuth CTP - Facebook的坏请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用CTP通过OAuth 2.0与Facebook连接。



我可以将Facebook的初始请求提供给Facebook,但是回到我们的电话:

  //其中null将成为HttpRequestInfo对象
client.ProcessUserAuthorization(null);

我得到:


远程服务器返回错误:(400)错误请求。


我的初始化并没有太多代码库;只将可选值设置为null(我们仍然在.NET 3.5)。任何线索都将不胜感激。



此外,我想这更是Andrew的一个问题。有没有一个论坛/博客的任何这些东西,或任何地方将定期更新?知道一些事情是非常好的:


  1. DotNetOpenAuth与OAuth 2.0的计划发布日期

  2. 无论.NET 4.0是否是先决条件

无论如何,任何建议都将是最受欢迎的。

解决方案

在遇到此问题后,我写了自己的代码进行授权,并获得用户的详细信息。另一种方法是使用 Facebook C#SDK 。作为任何人想要做自己的人的首发,这里是我如何做到的。请注意,我没有研究错误情况。



首先,

  private static readonly FacebookClient facebookClient = new FacebookClient(); 
public ActionResult LoginWithFacebook()
{
var result = facebookClient.Authorize();
if(result == FacebookAuthorisationResult.RequestingCode)
{
//客户端已经完成了一个Response.Redirect
return View();
} else if(result == FacebookAuthorisationResult.Authorized)
{
var user = facebookClient.GetCurrentUser();
}
返回重定向(/);
}

客户端代码:

 使用系统; 
使用System.IO;
使用System.Net;
使用System.Runtime.Serialization;
使用System.Runtime.Serialization.Json;
使用System.Text;
使用System.Web;

命名空间Web.Services
{
公开枚举FacebookAuthorisationResult
{
被拒绝,
授权,
请求代码
}
public class FacebookClient
{
private const String SESSION_NAME_TOKEN =UserFacebookToken;
public FacebookClient()
{
TokenEndpoint = new Uri(https://graph.facebook.com/oauth/access_token);
AuthorizationEndpoint = new Uri(https://graph.facebook.com/oauth/authorize);
MeGraphEndpoint = new Uri(https://graph.facebook.com/me);
ClientIdentifier =xxxxxxxxxxxxxxxxxx;
Secret =xxxxxxxxxxxx;
LocalSubDomain =local.xxxxxxx.com;
}

public Uri TokenEndpoint {get;组; }
public Uri AuthorizationEndpoint {get;组; }
public Uri MeGraphEndpoint {get;组; }
public String Secret {get;组; }
public String ClientIdentifier {get;组; }
private String LocalSubDomain {get;组; }


public FacebookAuthorisationResult授权()
{
var errorReason = HttpContext.Current.Request.Params [error_reason];
var userDenied = errorReason!= null;
if(userDenied)
返回FacebookAuthorisationResult.Denied;
var verificationCode = HttpContext.Current.Request.Params [code];
var redirectUrl = GetResponseUrl(HttpContext.Current.Request.Url);
var needToGetVerificationCode = verificationCode == null;
if(needToGetVerificationCode)
{
var url = AuthorizationEndpoint +? +
client_id =+ ClientIdentifier +& +
redirect_uri =+ redirectUrl;
HttpContext.Current.Response.Redirect(url);
返回FacebookAuthorisationResult.RequestingCode;
}
var token = ExchangeCodeForToken(verificationCode,redirectUrl);
HttpContext.Current.Session [SESSION_NAME_TOKEN] =令牌;
返回FacebookAuthorisationResult.Authorized;
}
public Boolean IsCurrentUserAuthorized()
{
return HttpContext.Current.Session [SESSION_NAME_TOKEN]!= null;
}
public FacebookGraph GetCurrentUser()
{
var token = HttpContext.Current.Session [SESSION_NAME_TOKEN];
if(token == null)
返回null;
var url = MeGraphEndpoint +? +
access_token =+ token;
var request = WebRequest.CreateDefault(new Uri(url));
使用(var response = request.GetResponse())
{
using(var responseStream = response.GetResponseStream())
{
using(var responseReader = new StreamReader(responseStream))
{
var responseText = responseReader.ReadToEnd();
var user = FacebookGraph.Deserialize(responseText);
返回用户;
}
}
}
}
private String ExchangeCodeForToken(String code,Uri redirectUrl)
{
var url = TokenEndpoint +? +
client_id =+ ClientIdentifier +& +
redirect_uri =+ redirectUrl +& +
client_secret =+ Secret +& +
code =+ code;
var request = WebRequest.CreateDefault(new Uri(url));
使用(var response = request.GetResponse())
{
using(var responseStream = response.GetResponseStream())
{
using(var responseReader = new StreamReader(responseStream))
{
var responseText = responseReader.ReadToEnd();
var token = responseText.Replace(access_token =,);
返回令牌;
}
}
}
}
私人Uri GetResponseUrl(Uri url)
{
var urlAsString = url.ToString();
var doesUrlContainQuestionMark = urlAsString.Contains(?);
if(doesUrlContainQuestionMark)
{
//删除任何参数。显然,Facebook不支持状态:http://forum.developers.facebook.net/viewtopic.php?pid=255231
//如果不这样做,您会得到验证验证码错误
urlAsString = urlAsString.Substring(0,urlAsString.IndexOf(?));
}
var replaceLocalhostWithSubdomain = url.Host ==localhost;
if(!replaceLocalhostWithSubdomain)
返回新的Uri(urlAsString);
// Facebook不喜欢本地主机,您只能使用配置的网址。要解决这个问题,请登录到Facebook
//并设置您的站点域设置,即happycow.com。
//下一个编辑C:\Windows\System32\drivers\etc\hosts,添加行:
// 127.0.0.1 local.happycow.cow
//最后,将LocalSubDomain设置为local.happycow.cow
urlAsString = urlAsString.Replace(localhost,LocalSubDomain);
返回新的Uri(urlAsString);
}
}
[DataContract]
public class FacebookGraph
{
private static DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(FacebookGraph));
//注意:从int32更改为字符串,基于Antonin Jelinek建议溢出
[DataMember(Name =id)]
public string Id {get;组; }

[DataMember(Name =name)]
public string Name {get;组; }

[DataMember(Name =first_name)]
public string FirstName {get;组; }

[DataMember(Name =last_name)]
public string LastName {get;组; }

[DataMember(Name =link)]
public Uri Link {get;组; }

[DataMember(Name =birthday)]
public string Birthday {get;组;

public static FacebookGraph Deserialize(string json)
{
if(String.IsNullOrEmpty(json))
{
throw new ArgumentNullException(json );
}

返回反序列化(新的MemoryStream(Encoding.UTF8.GetBytes(json)));
}

public static FacebookGraph Deserialize(Stream jsonStream)
{
if(jsonStream == null)
{
throw new ArgumentNullException jsonStream);
}

return(FacebookGraph)jsonSerializer.ReadObject(jsonStream);
}
}


}


I am trying to use the CTP to connect with Facebook over OAuth 2.0.

I can get the initial request to Facebook working OK, but when it comes back and we call:

// Where null will become an HttpRequestInfo object
client.ProcessUserAuthorization(null);

I get:

The remote server returned an error: (400) Bad Request.

I haven't really done much with the initial codebase; merely set the optional values to null (we're still on .NET 3.5). Any clues would be much appreciated.

Also, and i guess this is more of a question to Andrew specifically; is there a forum / blog for any of this stuff, or anywhere that will give regular updates? It would be great to know a few things:

  1. Planned release date of the DotNetOpenAuth with OAuth 2.0
  2. Whether .NET 4.0 will be a pre-requisite

Anyway, any suggestions would be most welcome.

解决方案

After hitting this issue, I wrote my own code to authorize, and get the users details. Another approach would be to use Facebook C# SDK. As a starter for anyone else thinking about doing there own, here is how I did it. Please note I have not looked into error cases.

Firstly, read facebooks doc on how it works (its rather simple!)

I consume it like this:

private static readonly FacebookClient facebookClient = new FacebookClient();
public ActionResult LoginWithFacebook()
{
    var result = facebookClient.Authorize();
    if (result == FacebookAuthorisationResult.RequestingCode)
    {
        //The client will have already done a Response.Redirect
        return View();
    } else if (result == FacebookAuthorisationResult.Authorized)
    {
        var user = facebookClient.GetCurrentUser();
    }
    return Redirect("/");
}

And the client code:

using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Web;

namespace Web.Services
{
    public enum FacebookAuthorisationResult
    {
        Denied,
        Authorized,
        RequestingCode
    }
    public class FacebookClient
    {
        private const String SESSION_NAME_TOKEN = "UserFacebookToken";
        public FacebookClient()
        {
            TokenEndpoint = new Uri("https://graph.facebook.com/oauth/access_token");
            AuthorizationEndpoint = new Uri("https://graph.facebook.com/oauth/authorize");
            MeGraphEndpoint = new Uri("https://graph.facebook.com/me");
            ClientIdentifier = "xxxxxxxxxxxxxxxxxx";
            Secret = "xxxxxxxxxxxx";
            LocalSubDomain = "local.xxxxxxx.com";
        }

        public Uri TokenEndpoint { get; set; }
        public Uri AuthorizationEndpoint { get; set; }
        public Uri MeGraphEndpoint { get; set; }
        public String Secret { get; set; }
        public String ClientIdentifier { get; set; }
        private String LocalSubDomain { get; set; }


        public FacebookAuthorisationResult Authorize()
        {
            var errorReason = HttpContext.Current.Request.Params["error_reason"];
            var userDenied = errorReason != null;
            if (userDenied)
                return FacebookAuthorisationResult.Denied;
            var verificationCode = HttpContext.Current.Request.Params["code"];
            var redirectUrl = GetResponseUrl(HttpContext.Current.Request.Url);
            var needToGetVerificationCode = verificationCode == null;
            if (needToGetVerificationCode)
            {
                var url = AuthorizationEndpoint + "?" +
                          "client_id=" + ClientIdentifier + "&" +
                          "redirect_uri=" + redirectUrl;
                HttpContext.Current.Response.Redirect(url);
                return FacebookAuthorisationResult.RequestingCode;
            }
            var token = ExchangeCodeForToken(verificationCode, redirectUrl);
            HttpContext.Current.Session[SESSION_NAME_TOKEN] = token;
            return FacebookAuthorisationResult.Authorized;
        }
        public Boolean IsCurrentUserAuthorized()
        {
            return HttpContext.Current.Session[SESSION_NAME_TOKEN] != null;
        }
        public FacebookGraph GetCurrentUser()
        {
            var token = HttpContext.Current.Session[SESSION_NAME_TOKEN];
            if (token == null)
                return null;
            var url = MeGraphEndpoint + "?" +
                      "access_token=" + token;
            var request = WebRequest.CreateDefault(new Uri(url));
            using (var response = request.GetResponse())
            {
                using (var responseStream = response.GetResponseStream())
                {
                    using (var responseReader = new StreamReader(responseStream))
                    {
                        var responseText = responseReader.ReadToEnd();
                        var user =  FacebookGraph.Deserialize(responseText);
                        return user;
                    }
                }
            }
        }
        private String ExchangeCodeForToken(String code, Uri redirectUrl)
        {
            var url = TokenEndpoint + "?" +
                      "client_id=" + ClientIdentifier + "&" +
                      "redirect_uri=" + redirectUrl + "&" +
                      "client_secret=" + Secret + "&" +
                      "code=" + code;
            var request = WebRequest.CreateDefault(new Uri(url));
            using (var response = request.GetResponse())
            {
                using (var responseStream = response.GetResponseStream())
                {
                    using (var responseReader = new StreamReader(responseStream))
                    {
                        var responseText = responseReader.ReadToEnd();
                        var token = responseText.Replace("access_token=", "");
                        return token;
                    }
                }
            }
        }
        private Uri GetResponseUrl(Uri url)
        {
            var urlAsString = url.ToString();
            var doesUrlContainQuestionMark = urlAsString.Contains("?");
            if (doesUrlContainQuestionMark)
            {
                // Remove any parameters. Apparently Facebook does not support state: http://forum.developers.facebook.net/viewtopic.php?pid=255231
                // If you do not do this, you will get 'Error validating verification code'
                urlAsString = urlAsString.Substring(0, urlAsString.IndexOf("?"));
            }
            var replaceLocalhostWithSubdomain = url.Host == "localhost";
            if (!replaceLocalhostWithSubdomain)
                return new Uri(urlAsString);
            // Facebook does not like localhost, you can only use the configured url. To get around this, log into facebook
            // and set your Site Domain setting, ie happycow.com. 
            // Next edit C:\Windows\System32\drivers\etc\hosts, adding the line: 
            // 127.0.0.1       local.happycow.cow
            // And lastly, set LocalSubDomain to local.happycow.cow
            urlAsString = urlAsString.Replace("localhost", LocalSubDomain);
            return new Uri(urlAsString);
        }
    }
    [DataContract]
    public class FacebookGraph
    {
        private static DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(FacebookGraph));
            // Note: Changed from int32 to string based on Antonin Jelinek advise of an overflow
        [DataMember(Name = "id")]
        public string Id { get; set; }

        [DataMember(Name = "name")]
        public string Name { get; set; }

        [DataMember(Name = "first_name")]
        public string FirstName { get; set; }

        [DataMember(Name = "last_name")]
        public string LastName { get; set; }

        [DataMember(Name = "link")]
        public Uri Link { get; set; }

        [DataMember(Name = "birthday")]
        public string Birthday { get; set; }

        public static FacebookGraph Deserialize(string json)
        {
            if (String.IsNullOrEmpty(json))
            {
                throw new ArgumentNullException("json");
            }

            return Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(json)));
        }

        public static FacebookGraph Deserialize(Stream jsonStream)
        {
            if (jsonStream == null)
            {
                throw new ArgumentNullException("jsonStream");
            }

            return (FacebookGraph)jsonSerializer.ReadObject(jsonStream);
        }
    }


}

这篇关于DotNetOpenAuth CTP - Facebook的坏请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆