OAuth授权的Java实现详解

由于最近在开发一个关于微博整合的小应用,于是开始接触各大微博平台的开放平台(新浪、搜狐、网易、QQ):目前这几大微博的应用开发都采用OAuth授权,要访问大部分API都需要OAuth方式的身份鉴权。

OAuth是什么?

先来简单介绍一下OAuth授权协议:OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时,任何第三方都可以使用OAuth认证服务,任何服务提供商都可以实现自身的OAuth认证服务,因而OAUTH是开放的。业界提供了OAuth的多种实现如PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间,因而OAuth是简易的。目前互联网很多服务如Open API,很多大头公司如Google,Yahoo,Microsoft等都提供了OAuth认证服务,这些都足以说明OAUTH标准逐渐成为开放资源授权的标准。

OAuth的授权流程

你所开发的应用需要流程如下:

  1. 向应用服务商(新浪、搜狐等微博)请求request_token。
  2. 得到request_token后重定向用户到服务商的授权页面。
  3. 如果用户选择授权你得应用,用request_token向服务商请求换取access_token。
  4. 得到access_token等信息访问受限资源。

而服务商相应的响应如下:

  1. 创建request_token返回给应用。
  2. 询问用户是否授权此应用。如果用户授权重定向用户至应用页面。
  3. 创建access_token并返回给应用。
  4. 响应受限资源请求并返回相关信息。

通俗点的说法就是“你拿着你得身份证明(request_token)向服务商申请进入用户家的门钥匙(access_token),服务商询问用户同不同意,如果用户同意服务商就给你进入用户家门的钥匙(access_token),拿到钥匙后你就可以进到用户家里”。

OAuth授权的Java实现

作为一个开放协议目前有很多现成的Oauth库可供开发者使用,可以点击这里下载。不过有精力有时间的话还是自己去实现一下OAuth授权的流程,可以很好的体会OAuth认证协议的原理。以

下面就是我使用Java实现Oauth的具体步骤,代码很简单,如果有画蛇添足的地方还望高手一笑而过。

一、获取Request_token

首先得准备一下参数及其来源:

  1. oauth_consumer_key —— 注册应用后由应用服务商提供
  2. consumer_secret —— 注册应用后由应用服务商提供
  3. oauth_callback —— 用户授权后的返回地址
  4. oauth_nonce —— 随机字符串,须保证每次都不同
  5. oauth_timestamp —— 时间戳
  6. oauth_signature_method —— 签名base string 的方法,目前支持 HMAC-SHA1
  7. oauth_version —— Oauth协议版本

还需要下面三个请求地址(这些地址任何一个提供OAuth的服务商都会提供给你,看下API文档就会找到):

  1. requst_token_url —— 上面第1步中的请求地址
  2. authorize_url —— 上面第2步的请求地址
  3. access_token_url —— 上面第3步的请求地址

至于如何注册应用,新浪微博点此,网易微博点此,腾讯微博点此,搜狐微博需要你发邮件索取,具体看这里。注册成功后就会获得oauth_consumer_key 和 consumer_secret 两个参数。

oauth_callback 起的作用是当用户授权成功后服务商会把用户重定向到这个网址。

oauth_nonce 是一个随机字符串下面是我的生成代码:

public String set_nonce() {
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 18; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}

oauth_timestamp 是请求的时间戳,我的代码如下:

public String set_timestamp() {

Date date = new Date();
long time = date.getTime();
return (time + "").substring(0, 10);
}

需要说明一下的是这里的时间戳为10位而不是13位,因此截取0-10位置。

其他参数直接指定就行了。

接下来,有了这些参数就可以组装base string了。准备base string的目的就是为了得到 oauth_signature 这个参数,这个参数向服务商发送请求的时候需要用到。

组装的方法是用下面8部分

  1. POST(也可以是GET,取决于你应用服务商支持哪个)。
  2. Urlencode之后的requst_token_url 。
  3. oauth_callback=Urlencode之后你的oauth_callback(Urlencode的参数为“utf-8”)。
  4. oauth_consumer_key = 你的oauth_consumer_key 
  5. oauth_nonce = 你的oauth_nonce 
  6. oauth_signature_method = 你的 oauth_signature_method 
  7. oauth_timestamp = 你的oauth_timestamp 
  8. oauth_version = “1.0”——目前大多数OAuth都采用的是1.0或1.0a版本。
需要注意的是上面除了1跟2外其他参数的格数形如: abc=“abc” ,然后先将上面1和2部分用&号相连得到串A、3-8部分用&相连得到串B,下面需要将串B再进行一次Urlencode得到串C,最后将A跟C以&号相连就得到了base string。这个过程中 oauth_callback 实质上经过了两次 Urlencode ,组装base string是非常容易出错的,一不小心丢一个引号或者格式稍有不对就会出错。

下面是我的Java实现代码:

public String set_basestring() throws UnsupportedEncodingException {
String bss;
bss = oauth_request_method + "&"
+ URLEncoder.encode(requst_token_url, "utf-8") + "&";
String bsss = "oauth_callback="
+ URLEncoder.encode(oauth_callback, "utf-8")
+ "&oauth_consumer_key=" + oauth_consumer_key + "&oauth_nonce="
+ oauth_nonce + "&oauth_signature_method="
+ oauth_signature_method + "&oauth_timestamp="
+ oauth_timestamp + "&oauth_version=" + oauth_version;
bsss = URLEncoder.encode(bsss, "utf-8");
return bss + bsss;
}

有了base string就可以签名生成oauth_signature这个参数,oauth_signature会在请求request_token的时候用到。签名算法是HMAC-SHA1,签名的key就是最开始的consumer_secret后加一个&号,签名算法代码如下:

public String hmacsha1(String data, String key) {
byte[] byteHMAC = null;
try {
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
mac.init(spec);
byteHMAC = mac.doFinal(data.getBytes());
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException ignore) {
}
String oauth = new BASE64Encoder().encode(byteHMAC);
return oauth;
}

里面用的的BASE64Encoder这个类可以Google一个。

得到oauth_signature后就要开始向 requst_token_url 发送请求了,OAuth规范定义了三种传递OAuth参数方式:

  1. httpheader中
  2. url中
  3. post form中

国内各大微博的支持情况是:新浪Httpheader可用,网易Httpheader可用,腾讯只支持在url,搜狐由于没有appkey所以还没去尝试。

如果使用Httpheader传递参数头名为“Authorization”,值为下面的格式,将值改为自己应用的。

OAuth oauth_nonce="9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1272323047", oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_token="8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc", oauth_verifier="pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY", oauth_signature="PUw%2FdHA4fnlJYM6RhXk5IU%2F0fCc%3D", oauth_version="1.0"

url和post form两种方式的参数名和参数值也即上面的,完全一样。

请求发送成功后就会得到的响应如下:

oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA&oauth_callback_confirmed=true

可以看到响应里面已经包含oauth_token和oauth_token_secret了,存贮之以备后面使用。

二、用户认证

拿到了oauth_token之后就需要用户对此oauth_token授权,也即对你的应用授权,具体做法就是发送oauth_token到服务商并请求用户对此oauth_token授权:实现方法为以oauth_token和oauth_callback为参数请求oauthorize_url,Servlet中的代码如下:

resp.sendRedirect(oauthorize_url+"?oauth_token="+oauth_token+"&oauth_callback="+oauth_callback);

 这是用户就被带到了应用授权页面,并可以选择是否对该应用授权。如果用户授权之后就会被带到oauth_callback 地址。同时如果需要服务商会给oauth_callback返会一个名为oauth_verifier的参数(此参数用于无法跳转的桌面应用,不一定每个微博平台都会返回),这时候我们的oauth_token已经获得用户的授权了。

三、用oauth_token换取access_token

这一步跟第一步“获取Request_token”基本相同,也是需要准备 base string 对其签名,然后发送请求,可以参考第一步的代码实现:但是相应的参数有所不用,具体来讲就是第一步组装base string 时候8个部分中第二个部分中的url换为access_token_url 并去掉oauth_callback加上oauth_token(如果有oauth_verifier的话也需要一并加上),组装好之后需要签名以得到oauth_signature,本次签名的方法跟上次一样,但是key变为consumer_secret和oauth_token_secret以&连接的串。

下来需要向access_token_url发送请求,请求参数包括base string 里的除了请求方法(POST或GET)和请求地址外的所有参数及其值和签名后生成的oauth_signature。例子如下:

OAuth oauth_nonce="9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1272323047", oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_token="8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc", oauth_verifier="pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY", oauth_signature="PUw%2FdHA4fnlJYM6RhXk5IU%2F0fCc%3D", oauth_version="1.0""

请求成功会服务商就会返回oauth_token和oaut_token_secret,这里的oauth_token和oaut_token_secret就是真正访问资源要用的access_token。

还需要说明的是以上过程只需要经行一次,就是说你拿到的access_token是不会过期的,除非用户手动将授权收回,因此作为access_token的oauth_token和oaut_token_secret要保存起来,以后访问受限资源的时候可以直接使用。至于如何访问受限资源,等以后有时间了再补上。

(本文系原创,转载请注明出处)

360全景制作的评论:

OAUTH标准逐渐成为开放资源授权的标准

电动螺旋压力机的评论:

谢谢博主分享,很不错!

丸美眼霜的评论:

OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。

tx的评论:

最近正在研究这部分,基本有个思路,但做到用户认证就卡住了,我已经拿到了requestToken,android应用怎么进行用户认证啊?劳驾帮忙看看。十分感谢。看到回复email
tx 于 2011-11-28 14:22:42 回复
引自 tx
最近正在研究这部分,基本有个思路,但做到用户认证就卡住了,我已经拿到了requestToken,android应用怎么进行用户认证啊?劳驾帮忙看看。十分感谢。看到回复email:549682063@qq.com

撒旦的评论:

POST(也可以是GET,取决于你应用服务商支持哪个)。
Urlencode之后的requst_token_url 。
oauth_callback=Urlencode之后你的oauth_callback(Urlencode的参数为“utf-8”)。
oauth_consumer_key = 你的oauth_consumer_key
oauth_nonce = 你的oauth_nonce
oauth_signature_method = 你的 oauth_signature_method
oauth_timestamp = 你的oauth_timestamp
oauth_version = “1.0”——目前大多数OAuth都采用的是1.0或1.0a版本。

這些是自己去設置的嗎?

达济学历教育的评论:

十分详细,看着复杂,不知实操怎样,有空试试、、

百家乐用品的评论:

谢谢分享 很不错的

comforterblogs的评论:

捣鼓新浪开发的使用见过这玩意,不过我用的是php

ecosway的评论:

写得不错分享了

硅谷教育博客的评论:

慢慢研究下

在这里给博主推荐一个不错的东东,中国第一部程序员题材的银幕电影《让爱飞》,观看地址:http://t.cn/alwuli

oauth协议的实现的评论:

你好,文章写得真好!我想问你点问题,就是oauth协议的服务器端实现方式是什么样子的呢?比如你把相应的参数出给对应的API接口地址,返回request_token。这是怎么返回的呢?服务器端怎么实现这种呢?谢谢您的回答!不胜感激。您能不能加我为好友啊。我的QQ号码:472398975

科士威的评论:

路过,学习一下!

mysupa的评论:

一、获取Request_token 3,6参数代表什么 怎么得到这个参数的值

cnfi的评论:

请问我使用拿到手的access_token和acces_token_secret在服务器端请求需要登录的接口,是否可以实现用户不用登录的情况下浏览受限制的页面了?比如sina微博的话题接口,需要用户登录,但是我希望用户不登陆情况下也能看到某个话题内容

电商圈的评论:

写得不错分享了

电商圈的评论:

路过,学习一下!

sprcen的评论:

运行结果:
警告: Unable to respond to any of these challenges: {oauth=OAuth realm="http%3A%2F%2Ftc137", oauth_signature="277F0Zzq97TBXYJybFMGTdIAkjg%3D", oauth_signature_base_string="GET%26http%253A%252F%252Fapi.t.sina.com.cn%252Foauth%252Frequest_token%26oauth_consumer_key%253D4101905547%2526oauth_nonce%253D6779916453%2526oauth_signature_method%253DHMAC-SHA1%2526oauth_timestamp%253D1305081297%2526oauth_version%253D1.0", oauth_signature_method="HMAC-SHA1", oauth_right_signature="tIZ0ln25VKTLIPAAQZXxfp61ej8%3D"}
request=%2Foauth%2Frequest_token&error_code=401&error=40107%3AOauth+Error%3A+signature_invalid%21&error_CN=%E9%94%99%E8%AF%AF%3A%E7%AD%BE%E5%90%8D%E5%80%BC%E4%B8%8D%E5%90%88%E6%B3%95%21

sprcen的评论:

代码:main
String data = Util.getHeader();
System.out.println(data);
HttpClient hc = new HttpClient();
GetMethod gm = new GetMethod("http://api.t.sina.com.cn/oauth/request_token");
Header header = new Header();
header.setName("Authorization");header.setValue(data);
gm.addRequestHeader(header);

int i = hc.executeMethod(gm);
System.out.println(gm.getResponseBodyAsString());


BASESTRING:
POST&http%3A%2F%2Fapi.t.sina.com.cn%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252F192.168.0.4%253A8080%252Fweiblog%252Fincom.jsp%26oauth_consumer_key%3D4101905547%26oauth_nonce%3D6779916453%26oauth_signature_method%3DHmacSHA1%26oauth_timestamp%3D1305081297%26oauth_version%3D1.0

header:
OAuth oauth_consumer_key="4101905547",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1305081297",oauth_nonce="6779916453",oauth_version="1.0",oauth_signature="277F0Zzq97TBXYJybFMGTdIAkjg%3D"
没找出来哪错了,40107说是签名错了555找死了!麻烦看看

小春哥的评论:

来看看,学习一下

fzcs的评论:

用httpclient的HttpGet的addHeader方法,具体你搜一下教程。

sprcen2的评论:

null:[HTTP/1.1 401 Unauthorized]
X-Varnish:[1024948961]
WWW-Authenticate:[OAuth realm=&quot;http%3A%2F%2Ftc143&quot;, oauth_signature=&quot;TtnibVrkSA7h9MO0ds3lcdC3T%2BE%3D&quot;, oauth_signature_base_string=&quot;POST%26http%253A%252F%252Fapi.t.sina.com.cn%252Foauth%252Frequest_token%26oauth_consumer_key%253D4101905547%2526oauth_nonce%253D6455235078%2526oauth_signature_method%253DHMAC-SHA1%2526oauth_timestamp%253D1304068672%2526oauth_version%253D1.0&quot;, oauth_signature_method=&quot;HMAC-SHA1&quot;, oauth_right_signature=&quot;8NGRN3wY3oF52kZXCvMN6S7WIyc%3D&quot;]
Age:[0]
SINA-LB:[eGQxNi5oYS54ZGdyb3VwMS5iai5sb2FkYmFsYW5jZQ==]
Date:[Fri, 29 Apr 2011 09:17:51 GMT]
Content-Length:[185]
Expires:[Thu, 01 Jan 1970 00:00:00 GMT]
Via:[1.1 varnish]
Server:[weibo]
Pragma:[No-cache]
Cache-Control:[no-cache]
Exception in thread &quot;main&quot; java.io.IOException: Server returned HTTP response code: 401 for URL: http://api.t.sina.com.cn/oauth/request_token

报401,找了好长时间没找出来,大侠帮我看看吧,谢了!

sprcen的评论:

输出的BASE STRING:
POST&amp;http%3A%2F%2Fapi.t.sina.com.cn%2Foauth%2Frequest_token&amp;oauth_callback%3Dhttp%253A%252F%252F192.168.0.4%253A8080%252Fweiblog%252Fincom.jsp%26oauth_consumer_key%3D4101905547%26oauth_nonce%3D6455235078%26oauth_signature_method%3DHmacSHA1%26oauth_timestamp%3D1304068672%26oauth_version%3D1.0

sprcen的评论:

执行后,反馈如下:
null:[HTTP/1.1 401 Unauthorized]
X-Varnish:[1024948961]
WWW-Authenticate:[OAuth realm=&quot;http%3A%2F%2Ftc143&quot;, oauth_signature=&quot;TtnibVrkSA7h9MO0ds3lcdC3T%2BE%3D&quot;, oauth_signature_base_string=&quot;POST%26http%253A%252F%252Fapi.t.sina.com.cn%252Foauth%252Frequest_token%26oauth_consumer_key%253D4101905547%2526oauth_nonce%253D6455235078%2526oauth_signature_method%253DHMAC-SHA1%2526oauth_timestamp%253D1304068672%2526oauth_version%253D1.0&quot;, oauth_signature_method=&quot;HMAC-SHA1&quot;, oauth_right_signature=&quot;8NGRN3wY3oF52kZXCvMN6S7WIyc%3D&quot;]
Age:[0]
SINA-LB:[eGQxNi5oYS54ZGdyb3VwMS5iai5sb2FkYmFsYW5jZQ==]
Date:[Fri, 29 Apr 2011 09:17:51 GMT]
Content-Length:[185]
Expires:[Thu, 01 Jan 1970 00:00:00 GMT]
Via:[1.1 varnish]
Server:[weibo]
Pragma:[No-cache]
Cache-Control:[no-cache]
Exception in thread &quot;main&quot; java.io.IOException: Server returned HTTP response code: 401 for URL: http://api.t.sina.com.cn/oauth/request_token

报401,找了好长时间没找出来,大侠帮我看看吧,谢了!

sprcen的评论:

BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String str = null;
while((str = br.readLine())!=null){
System.out.println(str);
}
sprcen2 于 2011-4-29 17:31:34 回复
null:[HTTP/1.1 401 Unauthorized]
X-Varnish:[1024948961]
WWW-Authenticate:[OAuth realm=&quot;http%3A%2F%2Ftc143&quot;, oauth_signature=&quot;TtnibVrkSA7h9MO0ds3lcdC3T%2BE%3D&quot;, oauth_signature_base_string=&quot;POST%26http%253A%252F%252Fapi.t.sina.com.cn%252Foauth%252Frequest_token%26oauth_consumer_key%253D4101905547%2526oauth_nonce%253D6455235078%2526oauth_signature_method%253DHMAC-SHA1%2526oauth_timestamp%253D1304068672%2526oauth_version%253D1.0&quot;, oauth_signature_method=&quot;HMAC-SHA1&quot;, oauth_right_signature=&quot;8NGRN3wY3oF52kZXCvMN6S7WIyc%3D&quot;]
Age:[0]
SINA-LB:[eGQxNi5oYS54ZGdyb3VwMS5iai5sb2FkYmFsYW5jZQ==]
Date:[Fri, 29 Apr 2011 09:17:51 GMT]
Content-Length:[185]
Expires:[Thu, 01 Jan 1970 00:00:00 GMT]
Via:[1.1 varnish]
Server:[weibo]
Pragma:[No-cache]
Cache-Control:[no-cache]
Exception in thread &quot;main&quot; java.io.IOException: Server returned HTTP response code: 401 for URL: http://api.t.sina.com.cn/oauth/request_token

报401,找了好长时间没找出来,大侠帮我看看吧,谢了!

sprcen的评论:

你好,请问HTTPHEADER是怎么通过JAVA/JSP发送的,我的代码:
String data = Util.getHeader();
URL url = new URL("http://api.t.sina.com.cn/oauth/request_token");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
conn.addRequestProperty("authorization", data);
conn.setDoOutput(true);
conn.setDoInput(true);
// System.out.println(conn.getResponseMessage()+"---");
Map<String, List<String>> headerMap = conn.getHeaderFields();
Iterator<String> iterator = headerMap.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
List<String> values = headerMap.get(key);
System.out.println(key + ":" + values.toString());
}
littlear 于 2011-4-29 20:33:12 回复
用httpclient的HttpGet的addHeader方法,具体你搜一下教程。

cjl的评论:

你就说了每个参数怎么生成,但是没有说生成后怎么办啊,怎么拼URL,我用的是GET方式,要一个完整的URL啊???代码只贴一点等于不贴
littlear 于 2011-4-7 22:41:52 回复
那你别看呗,我都说了这是 Httpheader 的例子。我怎么想怎么贴就怎么贴犯着你了?

cjl的评论:

按照你的方法生成了basestring和oauth_signature,然后拼装了URL:

String baseString = "";
try {
baseString = set_basestring();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
StringBuilder url = new StringBuilder();
url.append("?"
+
// "basestring=" + (baseString)+
"oauth_nonce=" + createRondomString() + "&oauth_signature="
+ hmacsha1(baseString, CONST.APP_SECRET + "&")
+ "&oauth_callback="
+ URLEncoder.encode("http://www.zepc.edu.cn")
+ "&oauth_consumer_key=" + CONST.APP_KEY
+ "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp="
+ createTimeStamp() + "&oauth_version=1.0");
Log.d(CONST.LOG_TAG, url.toString() + "url-->");
HttpConnect httpconn = new HttpConnect(CONST.REQUEST_URL
+ url.toString());
String responseData = httpconn.getDataAsString();
return responseData;
为什么 总是401错误呢????????????????????

中国美术高考网的评论:

学习了,呵呵
http://www.51meishu.com/

电视棒的评论:

写的不错,学习学习

茶苯海明的评论:

API文档真是要命啊

学习了~

不错的评论:

学习了http://www.by-healtha.com

很不错的评论:

希望继续http://www.mringe.com

131导航的评论:

131导航前来顶一下

后宫动漫的评论:

文章写的很不错,特地来支持你的,有时间也到我的博客看看http://www.hougongdongman.info

Mr.ing鞋神淘宝店的评论:

非常专业的文章,不错

乔伊思韩版女装的评论:

真的太难理解了!我不太明白!

瘦身咖啡的评论:

还在享受春节呢?呵呵

瘦手臂的评论:

和josn有什么区别呢。。大概意思一样啊。。

诺基亚5250主题下载的评论:

哇 太难理解了 我得慢慢研究

博客之家的评论:

我的技术是在太菜了。

粤语电影的评论:

假期都快完了.博主新年快乐.

博客之家的评论:

博主新年快乐。
littlear 于 2011-2-3 21:46:10 回复
新年快乐!

lei的评论:

你一和三的Httpheader参数是一样的.写错了吗?
littlear 于 2011-1-30 17:59:50 回复
额 不好意思 是我写错了。一根三应该不一样。
littlear 于 2011-2-3 2:41:43 回复
已修改

lei的评论:

如果使用Httpheader传递参数头名为“Authorization”,值为下面的格式,将值改为自己应用的。

OAuth oauth_nonce="9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1272323047", oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_token="8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc", oauth_verifier="pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY", oauth_signature="PUw%2FdHA4fnlJYM6RhXk5IU%2F0fCc%3D", oauth_version="1.0"

这个值要连成字符串吗?还是做成数组?做成字符串需要编码吗?
littlear 于 2011-1-29 13:34:32 回复
是字符串,各部分连接好以后不用编码。
lei 于 2011-1-29 14:58:46 回复
OAuth
这个“OAuth”和空格也要连上吗?
littlear 于 2011-1-29 20:37:50 回复
是的。 字符串OAuth后面有个空格,空格在整个字符串里面。
lei 于 2011-1-29 23:08:51 回复
再请教:
我的httpHeader是这样的:
//###################
OAuth oauth_nonce="1296312389172", oauth_callback="http%3A%2F%2Fg.cn", oauth_signature_method="HMAC=SHA1", oauth_timestamp="1296312389", oauth_consumer_key="1232068406", oauth_signature="b67212eb9134c8354f16fc1f7a42b55a5e4e7623", oauth_version="1.0"
// #####################################
我用下面代码(javascript),结果是:状态:0 回应的文本信息:
没用回应信息.也没有错误信息.我请求的是新浪的.请求失败不会有任何信息返回吗?我到底是错在哪里了?搞了2天2夜都没搞出来.求助
newXMLHttpRequest = new XMLHttpRequest();
newXMLHttpRequest.open("POST","http://api.t.sina.com.cn/oauth/request_token", true);
newXMLHttpRequest.setRequestHeader("Authorization",Header);

newXMLHttpRequest.onreadystatechange = function() {

if (newXMLHttpRequest.readyState == 4) {
document.writeln("状态:" + newXMLHttpRequest.status);
// alert(newXMLHttpRequest.statusText + ")");
document.writeln("回应的文本信息:" + newXMLHttpRequest.responseText);
}
};
newXMLHttpRequest.send();
alert("回应的文本信息:" + newXMLHttpRequest.responseText);
littlear 于 2011-1-30 5:34:54 回复
你的签名方法那里有错误:oauth_signature_method="HMAC-SHA1" 是 HMAC-SHA 你得是 HMAC=SHA
lei 于 2011-2-2 15:51:26 回复
搞了这么多天都搞定,总是返回null.真是搞不清问题出在哪里了.
组装的方法是用下面8部分

1. POST(也可以是GET,取决于你应用服务商支持哪个)。
2. Urlencode之后的requst_token_url 。
3. oauth_callback=Urlencode之后你的oauth_callback(Urlencode的参数为“utf-8”)。
4. oauth_consumer_key = 你的oauth_consumer_key
5. oauth_nonce = 你的oauth_nonce
6. oauth_signature_method = 你的 oauth_signature_method
7. oauth_timestamp = 你的oauth_timestamp
8. oauth_version = “1.0”——目前大多数OAuth都采用的是1.0或1.0a版本。

这个组装完后的字符串的值有引号吗?但是不管我加不加引号都是返回null,新浪api文档(http://open.t.sina.com.cn/wiki/index.php/Oauth)里的是没有引号的.不知道是不是文档有问题.你这篇是针对新浪的还是网易?
lei 于 2011-2-2 16:56:39 回复
alert("Error: status code is " + newXMLHttpRequest.status);
上面这行http状态码总是返回 0
lei 于 2011-2-2 22:56:13 回复
今天过年有好好磕头,终于返回401了.不再是0.下面是一些错误信息了.不知道错在哪里了.是请求方法不对还是字符串没构建不对.请帮帮忙:
响应:request=%2Foauth%2Frequest_token&error_code=401&error=40107%3AOauth+Error%3A+signature_invalid%21&error_CN=%E9%94%99%E8%AF%AF%3A%E7%AD%BE%E5%90%8D%E5%80%BC%E4%B8%8D%E5%90%88%E6%B3%95%21
响应头信息原始头信息
Pragma No-cache
Cache-Control no-cache
Expires Thu, 01 Jan 1970 00:00:00 GMT
WWW-Authenticate OAuth realm="http%3A%2F%2Ftc134", oauth_signature="epaCA%20xXTfvSO6hheKo3AS8VeBc", oauth_signature_base_string="POST%26http%253A%252F%252Fapi.t.sina.com.cn%252Foauth%252Frequest_token%26oauth_callback%253Dhttp%2525253A%2525252F%2525252F127.0.0.1%2525252F%2526oauth_consumer_key%253D1232068406%2526oauth_nonce%253DWedFeb022011224855GMT0800CST%2526oauth_signature_method%253DHMAC-SHA1%2526oauth_timestamp%253D1296658135%2526oauth_version%253D1.0", oauth_signature_method="HMAC-SHA1", oauth_right_signature="NH4DGlwhWp%2FzNH%2FCfR8OfcQk53I%3D"
Content-Length 185
Server weibo
Date Wed, 02 Feb 2011 14:48:53 GMT
littlear 于 2011-2-3 2:21:06 回复
请问你目前问题出在第几步?request token 获取不到还是? 组装basestring的话请仔细按照这句话来做:需要注意的是上面除了1跟2外其他参数的格数形如: abc=“abc” ,然后先将上面1和2部分用&号相连得到串A、3-8部分用&相连得到串B,下面需要将串B再进行一次Urlencode得到串C,最后将A跟C以&号相连就得到了base string。这个过程中 oauth_callback 实质上经过了两次 Urlencode ,组装base string是非常容易出错的,一不小心丢一个引号或者格式稍有不对就会出错。
littlear 于 2011-2-3 2:34:03 回复
兄弟,你basestring是错误的,自习看basestring是怎么组装的,最后basestring的成品里面 http://api.t.sina.com.cn/oauth/request_token 经过了一次urlencode,而你得call_back经过的两次urlencode,至于为什么是这样是组装方法决定的。仔细看我上面的黑字体,细心点,很简单的。
lei 于 2011-2-3 3:49:03 回复
非常感谢!在2011 03:43:11搞定,大过年的搞到03:43.谢谢!我真是太不仔细了,以后要改正这习惯.实际上我以前也很仔细的,工作忙没时间就什么事都涂快不仔细结果浪费更多时间.
littlear 于 2011-2-3 10:04:53 回复
客气,组装basestring一不小心就错,你当初仔细看我文章就不会错啦。

烟台SEO的评论:

貌似java很流行,可惜自己一点不懂

入团申请书的评论:

博客不错~拜读了!呵呵~!
有时间交流下哦!我的博客http://www.rutuanmm.com

GXG的评论:

这个知识有些复杂~~~

宁波网站建设的评论:

Java技术还是很不错的,现在有的人也很多啊。

翔子的评论:

我正漩在oauth痛苦的海洋,请把请求资源的方式给我发邮件,感激不尽。。。
littlear 于 2011-1-13 22:13:45 回复
抱歉,最近比较忙,请求资源的我还没做,不过你有什么问题可以和我探讨。

踏浪者的评论:

非常专业的文章,不错 !学习了
开发平台的人都是高手,只有佩服的份了

减肥食谱的评论:

给力支持,真是不容易啊

HexBolts的评论:

感觉OAuth比JAVA还难理解!~~~~~~~~

Mr.ing官网的评论:

非常专业的文章,不错 !学习了

李鸣帛博客的评论:

我是个菜鸟,你说的是什么我都不清楚。。。呵呵,但是看过之后还是学到啦!人啊,不怕落后,就怕不知道上进!期待你的回访~李鸣帛敬上

安全门的评论:

博主的技术不错哦,很深奥的技术。

安全门的评论:

很复杂的技术说明,博主技术不错哦!
由 littlear 于 2011-1-8 20:26:38 最后编辑

诺贝笔翻译公司的评论:

非常专业的文章,不错

网站检测的评论:


觉得楼主说得挺有道理的,但实际操作,难度就高很多了。
littlear 于 2011-1-6 18:01:01 回复
只要按着步骤来,细心点很容易的,当然编程基础还是要有的。

EyeNuts的评论:

非常不错,顶一下

黑咖啡减肥的评论:

介绍的很详细,谢谢
littlear 于 2011-1-6 18:53:44 回复
这都是 我走弯路后总结出来的

珠宝的评论:

写得太好了,

oschina的评论:

转发了 http://www.oschina.net/bbs/thread/14739
littlear 于 2011-1-3 18:39:03 回复
已更新,欢迎转载完整版。

发表评论:

网站分类

最新评论及回复

文章归档