zoukankan      html  css  js  c++  java
  • 豆瓣api之OAuth认证

    豆瓣api通过OAuth允许第三方应用访问用户数据,所以OAuth认证就是我们整个project的基础了。

    OAuth认证听起来挺神秘,其实挺简单的。

    现在的大型网站的开放平台的认证几乎都是采用OAuth,比如facebook,twitter,新浪微博等。

    豆瓣的api有对于OAuth认证的专门说明:http://www.douban.com/service/apidoc/auth

    在你使用OAuth认证之前,先仔细读一读文档非常有必要,因为中间过程出现一点偏差,你就不能被认证成功,所以仔细阅读官方文档是重中之重:http://oauth.net/documentation/spec/

    如果你的英文不够给力的话,可以看看这篇中文的介绍,说的很清楚:http://www.supidea.com/post/oauth.aspx

    google OAuth项目已经提供了OAuth的各种语言的库:http://code.google.com/p/oauth/

    我们正式使用了google OAuth中的C#库: http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs

    因为OAuth已经成为了第三方开发者使用豆瓣api的一大障碍,豆瓣曾经专门举办了一次活动来讲解如何通过OAuth使用豆瓣api:http://www.douban.com/online/10012959/

    这次活动的源码在google code上可以找到:http://code.google.com/p/douban-oauth-sample/,我们正式参考了http://code.google.com/p/douban-oauth-sample/source/browse/trunk/csharp/DoubanOAuthBasicSample/DoubanOAuthBasicSample/Program.cs这个文件,对我们的帮助很大,省去了很多摸索的时间

    作为命令行程序我们已经测试成功了,但是当移植到windows phone上之后就出现了问题

    问题的关键在于silverlight版的网络方面的api和C#的不同,silverlight的api更少,这就导致了上面的库的一些网络访问要自己改写

    仔细阅读httpwebrequest的文档后,我们发现,要进行一个网络请求,至少要三个函数,因为需要使用两次异步请求(BeginGetRequestStream, BeginGetResponse)

    因为我们的豆瓣app几乎每个动作都要对豆瓣服务器进行请求,如果每个请求都需要写三个函数,并且还要增加认证信息的话,实在是太麻烦,代码会变得又臭又长

    这时候DRY(don’t repeat yourself)就显得尤为重要了

    作为pm,我决定把网络访问这一块封装好,给大家提供统一的,简单好用的借口。

    我本准备自己把那两个异步请求封装起来,后来发现已经有现成的库可用,而且很好很强大。

    这个库就是restsharp:http://restsharp.org/

    而且restsharp还提供了windows phone对应的dll,很是方便,原来的三个函数现在只需要一个函数几行就可以搞定

    对于很多请求,豆瓣都要求有认证才可以访问,根据豆瓣的文档“进行POST、PUT、DELETE请求时,豆瓣暂时不支持使用在url中或者post form中传递OAuth参数。因此你只能选择在header中传递OAuth参数”,看来我们只能把oauth加到http header中了。

    我部分我统一封装了一下:
    namespace AddOAuthHeader{
        public class OAuthHeader{
            string apiKey = "your api key";
            string apiKeySecret = "your api key secret";
            string accessToken;
            string accessTokenSecret;
            string uri;
            string method;
            OAuthBase oAuth = new OAuthBase();
            IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;

            public OAuthHeader(string uri, string method) {
                this.uri = uri;
                this.method = method;
            }

            public string getHeader(){
                string nonce = oAuth.GenerateNonce();
                string timeStamp = oAuth.GenerateTimeStamp();
                string normalizeUrl, normalizedRequestParameters;

                //accessToken = settings["accessToken"].ToString();
                //accessTokenSecret = settings["accessTokenSecret"].ToString();

                accessToken = "ee7ead643e6ea1a1cb7c082cbb4be4e3";
                accessTokenSecret = "545138430a2dcc9b";

                string sig = oAuth.GenerateSignature(
                    new Uri(uri),
                    apiKey,
                    apiKeySecret,
                    accessToken,
                    accessTokenSecret,
                    method,
                    timeStamp,
                    nonce,
                    OAuthBase.SignatureTypes.HMACSHA1,
                    out normalizeUrl,
                    out normalizedRequestParameters);
                sig = HttpUtility.UrlEncode(sig);

                StringBuilder oauthHeader = new StringBuilder();
                oauthHeader.AppendFormat("OAuth realm="", oauth_consumer_key={0}, ", apiKey);
                oauthHeader.AppendFormat("oauth_nonce={0}, ", nonce);
                oauthHeader.AppendFormat("oauth_timestamp={0}, ", timeStamp);
                oauthHeader.AppendFormat("oauth_signature_method={0}, ", "HMAC-SHA1");
                oauthHeader.AppendFormat("oauth_version={0}, ", "1.0");
                oauthHeader.AppendFormat("oauth_signature={0}, ", sig);
                oauthHeader.AppendFormat("oauth_token={0}", accessToken);

                return oauthHeader.ToString();
            }
        }
    }

    传入一个url和一个方法(post or put or delete or get),我就给他返回一个oauth header,其他同学直接调用我的代码就好了,并不需要关心认证问题

    那具体该如何来进行一个网络请求呢?

    我写了两个例子,一个post的,一个get的。

    向豆瓣传数据,post:(我把说明都写到了注释中)

    // "POST" 实例,以发一条状态为例
    private void button1_Click(object sender, RoutedEventArgs e)
    {
        //首先都要先实例化一个OAuthHeader,传入的参数为url和网络请求的方法(post or get or delete or put or something else)
        OAuthHeader header = new OAuthHeader("http://api.douban.com/miniblog/saying", "POST");

        //对于post,要传给服务器一些数据,豆瓣api用xml来传数据,就需要先build一个xml的string
        StringBuilder requestBody = new StringBuilder("<?xml version='1.0' encoding='UTF-8'?>");
        requestBody.Append("<entry xmlns:ns0="http://www.w3.org/2005/Atom" xmlns:db="http://www.douban.com/xmlns/">");
        requestBody.Append("<content>hello world</content>");
        requestBody.Append("</entry>");

        //下面两行是每一个网络请求都需要的,即与api.douban.com建立一个连接
        var client = new RestClient();
        client.BaseUrl = "http://api.douban.com";

        //下面这行的意思是产生一个请求,第一个参数是路径名(不是完整的url),后面是Method.POST 或 Method.GET 或Method.PUT 或 Method.DELETE
        var request = new RestRequest("/miniblog/saying", Method.POST);

        //下面进行一些http头的设置

        //先设置request的format为xml
        request.RequestFormat = DataFormat.Xml;
        request.AddHeader("Content-Type", "application/atom+xml");

        //然后是把生成的authorization写入http的header
        request.AddHeader("Authorization", header.getHeader());

        //最终把要上传的数据写入http请求中,注意要加上ParameterType.RequestBody
        request.AddParameter("application/atom+xml", requestBody.ToString(), ParameterType.RequestBody);

        //最后就是进行异步网络请求了,并且将传回的response的信息解析出来,呈现在页面上
        client.ExecuteAsync(request, (response) =>
        {
            var resource = response.Content;
            Debug.WriteLine(resource);
        });
    }

    //GET实例,以获取好友列表为例,get比较简单,不需要传入数据
    private void button3_Click(object sender, RoutedEventArgs e)
    {
        //同上
        OAuthHeader header = new OAuthHeader("http://api.douban.com/people/34788764/contacts?start-index=1&max-results=50", "GET");

        var client = new RestClient();
        client.BaseUrl = "http://api.douban.com";

        //注意,这里生成request的时候,不要把?后面的parameter加上,parameter要在后面的request.AddParameter处实现
        var request = new RestRequest("/people/34788764/contacts", Method.GET);

        //加上认证头
        request.AddHeader("Authorization", header.getHeader());

        //加上参数
        request.AddParameter("start-index", "1");
        request.AddParameter("max-results", "50");

        client.ExecuteAsync(request, (response) =>
        {
            var resource = response.Content;
            Debug.WriteLine(resource);
            textBlock1.Text = resource;
        });
    }

    这样就可以大大简化网络请求,真正做到了don’t repeat yourself

  • 相关阅读:
    vue 中简单路由的实现
    Vue中对生命周期的理解
    内存泄漏
    前端工程化
    exports 和 module.exports 的区别
    Nodejs的url模块方法
    MongoDB 的获取和安装
    Anjular JS 的一些运用
    移动端vconsole调试
    安装fiddler时,电脑浏览器没网
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3238847.html
Copyright © 2011-2022 走看看