oauth 手写_OAuth的各种点滴,不要去看新浪微博API文档!

OAuth的各种点滴,不要去看新浪微博API文档!

最近一段时间做和微博有关的pc客户端,包括了新浪,搜狐,腾讯,嘀咕,饭否。(目前在考虑要不要包含网易,它不支持XAuth认证,除非是邀请方。)

发现有个问题就是如果你跟着新浪微博API文档来做你的XAuth的话,你会很苦恼的。我就遇到各种各样的问题,这里从头到尾细细道来和大家分享,希望能给遇到相同问题的同胞们一些小小的帮助。

下面的内容全部是基于c++,libcurl库写的。

1.XAuth时token不合法。

不知道有多少人刚开始使用的时候遇到invalid

token,token不合法。

在最开始的时候我完全不知道这是什么状况。后来才明白了。你需要给你的http请求加一个http头。

对libcurl就是要有一个:

curl_slist *sHttpHead = NULL;

sHttpHead = curl_slist_append(sHttpHead, SomeAnsiChar);

以及

curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, sHttpHead);

SomeAnsiChar的内容是:

Authorization: OAuth oauth_cusumer_key="xxx", oauth_version="1.0",

...

按照新浪的文档说的是你需要把xauth_xxx也放进去,我不知道这么做是否是正确的,可能也能通。

按照twitter的做法,xauth_xxx是放在postfield里面的

另外,source完全不需要。

不要去看新浪文档写的!真头大!首先没说这个Authorization头的问题,然后source是完全不需要的(本来你就放了cosumer_key了,为啥还要source呢,然后xauth_xxx都是放到postfield里面的。)

2.Basestring的生成。

这个很容易让人困惑,什么需要编进basestring,什么不需要?比如说我看讨论区里面就有人说source要不要编进去。

还有,所有参数需要urlencode两遍。这一点恐怕也是大家经过一些invalid signature后才发现的。

OAuth.com/core/1.0

里面有很明确的指明了:

5.1. Parameter

Encoding

All parameter

names and values are escaped using the [RFC3986] percent-encoding

(%xx) mechanism. Characters not in the unreserved character set

([RFC3986] section 2.3) MUST be encoded. Characters in the

unreserved character set MUST NOT be encoded. Hexadecimal

characters in encodings MUST be upper case. Text names and values

MUST be encoded as UTF-8 octets before percent-encoding them per

[RFC3629].

unreserved = ALPHA, DIGIT, '-', '.', '_', '~'

5.2. Consumer Request

Parameters

OAuth Protocol

Parameters are sent from the Consumer to the Service Provider in

one of three methods, in order of decreasing preference:

In the HTTP

Authorization header as defined in OAuth HTTP Authorization

Scheme.

As the HTTP POST request body with a content-type of

application/x-www-form-urlencoded.

Added to the URLs in the query part (as defined by [RFC3986]

section 3).

In addition to these defined methods, future extensions may

describe alternate methods for sending the OAuth Protocol

Parameters. The methods for sending other request parameters are

left undefined, but SHOULD NOT use the OAuth HTTP Authorization

Scheme header.

9.1.1. Normalize Request

Parameters

The request

parameters are collected, sorted and concatenated into a normalized

string:

Parameters in the

OAuth HTTP Authorization header excluding the realm

parameter.

Parameters in the HTTP POST request body (with a content-type of

application/x-www-form-urlencoded).

HTTP GET parameters added to the URLs in the query part (as defined

by [RFC3986] section 3).

The oauth_signature parameter MUST be excluded.

The parameters are

normalized into a single string as follows:

Parameters are

sorted by name, using lexicographical byte value ordering. If two

or more parameters share the same name, they are sorted by their

value. For example:

a=1, c=hi there, f=25, f=50, f=a, z=p, z=t

Parameters are concatenated in their sorted order into a single

string. For each parameter, the name is separated from the

corresponding value by an ‘=’ character (ASCII code 61), even if

the value is empty. Each name-value pair is separated by an

‘&’ character (ASCII code 38). For example:

a=1&c=hi%20there&f=25&f=50&f=a&z=p&z=t

需要编进去的参数包括

1.Authorization:

头中,除了oauth_signature之外(因为它是最后生成的签名)的所有参数,比如oauth_version这些

2.postfields里面的所有参数。OAuth.com/core/1.0似乎指明了是application/x-www-form-urlencode中的。(formdata-mutipart呢?)

3.url中的参数。比如使用get方法的时候http://xxx?aa=bb这个aa=bb

这些参数是urlencode好的,比如你的postfield里面有status=��

写进去的时候就是status=��

然后把它们排序连起来

比如:

aa=bb&oauth_version=1.0&oauth_signature_method=HMAC-SHA1&status=%AA%BB

参数名称一样的按照参数值排序(这个没有遇到过)

aa=bb&oauth_version=1.0&oauth_signature_method=HMAC-SHA1&status=%AA%BB

然后再urlencode一遍。

所以你看到后面status是urlencode两遍了的。

然后再与http方法和encode好的url连起来:

比如:

POST&http%3A%2F%2Fxxx.com&aa%3Dbb%26oauth_signature_method%3DHMAC-SHA1%26oauth_version%3D1.0%26status%3D%25AA%25BB

这个就是basestring了(我没写完整啊!就是大概示意一下~)。

所以如果你传Source的话,就要加source,不传就不加。实际上我做完一遍发现没有需要传source的地方。

3.生成签名。

生成签名主要有3个地方容易出问题:

如果你有invalid signature的话可以看下这三个地方:

(1)确保你的HMAC-SHA1算法是正确的。

这一点新浪微博API文档极其郁闷的直接抄袭了twitter文档中的内容。我可以保证

比如文档中的:

第一步,准备base

string(使用上文提到的方法)

POST&https%3A%2F"5Fapi.t.sina.com.cn%2Foauth%2Faccess_token&oauth_consumer_key%3DGDdmIQH6jhtmLUypg82g%26oauth_nonce%3D9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1272323047%26oauth_token%3D8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc%26oauth_verifier%3DpDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY%26oauth_version%3D1.0

接着将consumer_secret和oauth_token_secret连接起来,中间用&分割(这是准备密钥的方法,下面还会用到):

MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98&x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA

生成的OAuth签名如下:

PUw/dHA4fnlJYM6RhXk5IU/0fCc=

最后那个签名你是得不到和他相同的。因为那个签名实际上是basestring用的是:(这个把我郁闷坏了!)

POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Faccess_token&oauth_consumer_key%3DGDdmIQH6jhtmLUypg82g%26oauth_nonce%3D9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8%26oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1272323047%26oauth_token%3D8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc%26oauth_verifier%3DpDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY%26oauth_version%3D1.0

生成签名的时候SHA1算法尤其要注意一下有一个问题。

如果你写了MD5的话,你传DWORD进去,用DWORD算,算完后直接用DWORD来写成字符串,是对的。

但是对于SHA1算法,你要传BYTE进去,用DWORD算,然后换成BYTE。

比如说吧,你的字符串是这样的:

abcd

那么你用MD5,算之前,第一个DWORD是这样的,0x64636261

(比如:

char * mystring = "abcd";

DWORD dwValue = 0;

memcpy(&dwValue, mystring, 4);

这个dwValue就是0x64636261)

但是你用SHA1的时候,第一个DWORD应该是0X61626364才是正确的。

出来的时候也一样。

比如你最后的MD5算出来的4个DWORD中间,第一个是0X61626364,那么写出来的字符串就是61626364

如果你用SHA1算出来的5个DWORD中,第一个是0X61626364,写错来的字符串就是64636261

(2)你的urlencode是否正确。

比如~-._是不进行urlencode的。具体什么需要urlencode什么不需要呢?这个我到现在还没完全明白。不过有一点就是在使用新浪的api的时候,不需要encode的一定不要,需要encode的你可以不encode。

比如账号中的@,你是否encode都行。(对于sohu就不行!)

此外,空格要encode成%20

对于ie,经过实验,它会encode这些:

!"#$%&`'(),/:;<=>?[]^{|}~%+*

去掉其中的~,加上@,经过实验,目前没有遇到问题。

按照OAuth.com/core/1.0的说法,除了

字母,数字, '-', '.', '_', '~'

其它一律encode。

我没有试过这种的。应该按照这个标准做是最好的。

(3)是不是全都encode好了?

除了status这样的需要encode两遍的以外,还特别要注意:

OAuth.com/core/1.0/

9.2. HMAC-SHA1

The HMAC-SHA1

signature method uses the HMAC-SHA1 signature algorithm as defined

in [RFC2104] where the Signature Base String is the text and the

key is the concatenated values (each first encoded per Parameter

Encoding) of the Consumer Secret and Token Secret, separated by an

‘&’ character (ASCII code 38) even if

empty.

也就是说你的oauth_secret也需要urlencode的。

这个对于sohu来说要特别注意,因为sohu给出来的secret里面有小括号的。

4.腾讯

腾讯不支持XAuth,即便如此程序还是可以实现模拟。

我前面有篇博客讲了怎么模拟浏览器登陆腾讯微博。

(如果你得到cResultL7,检查下是不是cookie文件没带上)

5.https

另外腾讯前面几步只支持https,这里顺便说一下怎么让你的libcurl支持https

本来如果不是liboauth需要openssl,我就用liboauth了,后来做到腾讯了才发现逃不掉。

下载openssl(1.0.0.d)http://openssl.org/source/

下载nasm(2.10rc4)http://www.nasm.us/pub/nasm/releasebuilds/2.10rc4/

下载activeperl(5.12.3.1204)http://www.activestate.com/activeperl/downloads

按照nasm介绍的build

nasm(nmake /f mkfiles/msvc.mak),如果你用vs2008会遇到一个error

把preproc.c 2744行 xxx->nolist =

NULL;改成xxx->nolist = 0;

安装perl

编译openssl(需要static版本的,make的时候用nt.mak而不是文档中说的ntdll.mak)

编译libcurl,你需要在con-win32.h里面加入(注意他有两个一个在src目录,一个在lib目录,这个要lib目录)

#define USE_SSLEAY 1

#define USE_OPENSSL 1

#pragma comment(lib, "../dependency/openssl/libeay32.lib")

#pragma comment(lib, "../dependency/openssl/ssleay32.lib")

附加包含头目录也要加上openssl的inc32

做https请求的时候,要加上:

curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, FALSE);

此外对sina说推荐用https,我尝试过了,总是无法连接。。。

6.一个接口的细节:upload

对于新浪,饭否,formdata里面的status不要urlencode

对于搜狐,嘀咕,需要。

饭否会发出来一堆%xx%xx之类的。

新浪会报invalid signature错误。

腾讯?人家是放到url里面的!

7.关于单次值。

我之前用时间进行MD5编码生成的(听说腾讯要求必须是32位,没试过不是32位的,新浪,搜狐这些试过了你可以随便做),请千万不要这样!~

不然的话你有可能在同一个时间发了两个单次值一样的请求。。。

就这些啦,其实我感觉遇到的最主要的问题还是urlencode的问题。这个一定要好好检查!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值