如何使用 java 获取 Google 的 OAuth 请求令牌
当我尝试访问 API 时,我很难从 google 获取请求令牌。我收到了标准 400 响应。我发送的请求几乎与他们提供的 OAuth 游乐场中生成的请求相同。
我使用匿名秘密/密钥并构造了一个基本字符串,如下所示:
GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dhttp%253A%252F%252Fgooglecodesamples.com%252Foauth_playground%252Findex.php%26oauth_consumer_key%3Danonymous%26oau th_nonce%3D61dddc084c4e8adfa13d1509161939b0%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D13028 53379%26oauth_version%3D1.0%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fcalendar%252Ffeeds%252F
为了调试正在发送的请求,我在 eclipse 中设置了 TCP/IP 监控。然而,这仅监视 Http 流量,因此以下内容 99% 反映了所请求的内容。
GET /accounts/OAuthGetRequestToken?scope=http%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2F HTTP/1.1
Authorization: OAuth oauth_callback="http%3A%2F%2Fgooglecodesamples.com%2Foauth_playground%2Findex.php", oauth_consumer_key="anonymous", oauth_nonce="8cc04c7633db041dd0fd8e5fd0eb728e", oauth_signature="epRa5IZOA6s%2B3qhZa%2FUxuwYKnJA%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1302790583", oauth_version="1.0"
Accept: */*
User-Agent: Java/1.6.0_24
Host: localhost
Connection: keep-alive
你能告诉我我做错了什么吗?提前致谢。
以下是我为此使用的唯一代码。
package com.pdw.gb;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.google.gdata.util.common.util.Base64;
public class OAuthTest3 {
public static String read(String url)
{
StringBuffer buffer = new StringBuffer();
try
{
String[][] data = {
{ "oauth_callback", URLEncoder.encode("http://googlecodesamples.com/oauth_playground/index.php","UTF-8") },
{ "oauth_consumer_key", "anonymous" },
{ "oauth_nonce", a64BitRandomString() },
{ "oauth_signature_method", "HMAC-SHA1" },
{ "oauth_timestamp", timeSinceEpochInMillis() },
{ "oauth_signature", "" },
{ "oauth_version", "1.0" },
{ "scope", URLEncoder.encode("https://www.google.com/calendar/feeds/","UTF-8") }
};
/**
* Generation of the signature base string
*/
String signature_base_string = "GET&"
+ URLEncoder.encode(url, "UTF-8") + "&";
for (int i = 0; i < data.length; i++)
{
// ignore the empty oauth_signature field
if (i != 5)
{
System.out.print(i);
signature_base_string += URLEncoder.encode(data[i][0],
"UTF-8")
+ "%3D"
+ URLEncoder.encode(data[i][1], "UTF-8") + "%26";
}
}
// cut the last appended %26
signature_base_string = signature_base_string.substring(0,
signature_base_string.length() - 3);
/**
* Sign the request
*/
Mac m = Mac.getInstance("HmacSHA1");
m.init(new SecretKeySpec("anonymous".getBytes(), "HmacSHA1"));
m.update(signature_base_string.getBytes());
byte[] res = m.doFinal();
String sig = URLEncoder.encode(String.valueOf(Base64.encode(res)),"UTF8");
data[5][1] = sig;
/**
* Create the header for the request
*/
String header = "OAuth ";
int i=0;
for (String[] item : data)
{
if (i!=7)
{
header += item[0] + "=\"" + item[1] + "\", ";
}
i++;
}
// cut off last appended comma
header = header.substring(0, header.length() - 2);
System.out.println("Signature Base String: "
+ signature_base_string);
System.out.println("Authorization Header: " + header);
System.out.println("Signature: " + sig);
String charset = "UTF-8";
URLConnection connection = new URL(url+"?scope="+URLEncoder.encode("https://www.google.com/calendar/feeds/", "UTF-8")).openConnection();
connection.setRequestProperty("Authorization", header);
connection.setRequestProperty("Accept", "*/*");
BufferedReader reader = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String read;
while ((read = reader.readLine()) != null)
{
buffer.append(read);
}
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
public static void main(String[] args)
{
boolean debug=false;
if (!debug)
{
System.out.println(OAuthTest3
.read("https://www.google.com/accounts/OAuthGetRequestToken"));
}
else
{
System.out.println(OAuthTest3
.read("http://localhost/accounts/OAuthGetRequestToken"));
}
}
private static String a64BitRandomString() {
StringBuffer sb = new StringBuffer();
Random generator = new Random();
for (int i = 0; i < 32; i++) {
Integer r = generator.nextInt();
if (r < 0) {
r = r * -1;
}
r = r % 16;
sb.append(r.toHexString(r));
}
return sb.toString();
}
private static String timeSinceEpochInMillis() {
Calendar c = Calendar.getInstance();
Date date = c.getTime();
Long time = date.getTime();
Integer i = (int) (time/1000);
return i.toString();
}
}
I'm struggling to fetch a request token from google when trying to access the APIs. I'm receiving the standard 400 response. The request i'm sending is almost identical to that generated in the OAuth playground they provide.
I'm using the anonymous secret/key and have constructed a base string as follows :
GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_callback%3Dhttp%253A%252F%252Fgooglecodesamples.com%252Foauth_playground%252Findex.php%26oauth_consumer_key%3Danonymous%26oauth_nonce%3D61dddc084c4e8adfa13d1509161939b0%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1302853379%26oauth_version%3D1.0%26scope%3Dhttps%253A%252F%252Fwww.google.com%252Fcalendar%252Ffeeds%252F
To debug the request being sent I setup TCP/IP monitoring in eclipse. However this only monitors Http traffic so the follwing is a 99% reflection of what is being requested.
GET /accounts/OAuthGetRequestToken?scope=http%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2F HTTP/1.1
Authorization: OAuth oauth_callback="http%3A%2F%2Fgooglecodesamples.com%2Foauth_playground%2Findex.php", oauth_consumer_key="anonymous", oauth_nonce="8cc04c7633db041dd0fd8e5fd0eb728e", oauth_signature="epRa5IZOA6s%2B3qhZa%2FUxuwYKnJA%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1302790583", oauth_version="1.0"
Accept: */*
User-Agent: Java/1.6.0_24
Host: localhost
Connection: keep-alive
Can you tell me what I'm doing wrong? Thanks in advance.
Below is the the only code i'm using for this.
package com.pdw.gb;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.google.gdata.util.common.util.Base64;
public class OAuthTest3 {
public static String read(String url)
{
StringBuffer buffer = new StringBuffer();
try
{
String[][] data = {
{ "oauth_callback", URLEncoder.encode("http://googlecodesamples.com/oauth_playground/index.php","UTF-8") },
{ "oauth_consumer_key", "anonymous" },
{ "oauth_nonce", a64BitRandomString() },
{ "oauth_signature_method", "HMAC-SHA1" },
{ "oauth_timestamp", timeSinceEpochInMillis() },
{ "oauth_signature", "" },
{ "oauth_version", "1.0" },
{ "scope", URLEncoder.encode("https://www.google.com/calendar/feeds/","UTF-8") }
};
/**
* Generation of the signature base string
*/
String signature_base_string = "GET&"
+ URLEncoder.encode(url, "UTF-8") + "&";
for (int i = 0; i < data.length; i++)
{
// ignore the empty oauth_signature field
if (i != 5)
{
System.out.print(i);
signature_base_string += URLEncoder.encode(data[i][0],
"UTF-8")
+ "%3D"
+ URLEncoder.encode(data[i][1], "UTF-8") + "%26";
}
}
// cut the last appended %26
signature_base_string = signature_base_string.substring(0,
signature_base_string.length() - 3);
/**
* Sign the request
*/
Mac m = Mac.getInstance("HmacSHA1");
m.init(new SecretKeySpec("anonymous".getBytes(), "HmacSHA1"));
m.update(signature_base_string.getBytes());
byte[] res = m.doFinal();
String sig = URLEncoder.encode(String.valueOf(Base64.encode(res)),"UTF8");
data[5][1] = sig;
/**
* Create the header for the request
*/
String header = "OAuth ";
int i=0;
for (String[] item : data)
{
if (i!=7)
{
header += item[0] + "=\"" + item[1] + "\", ";
}
i++;
}
// cut off last appended comma
header = header.substring(0, header.length() - 2);
System.out.println("Signature Base String: "
+ signature_base_string);
System.out.println("Authorization Header: " + header);
System.out.println("Signature: " + sig);
String charset = "UTF-8";
URLConnection connection = new URL(url+"?scope="+URLEncoder.encode("https://www.google.com/calendar/feeds/", "UTF-8")).openConnection();
connection.setRequestProperty("Authorization", header);
connection.setRequestProperty("Accept", "*/*");
BufferedReader reader = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String read;
while ((read = reader.readLine()) != null)
{
buffer.append(read);
}
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
public static void main(String[] args)
{
boolean debug=false;
if (!debug)
{
System.out.println(OAuthTest3
.read("https://www.google.com/accounts/OAuthGetRequestToken"));
}
else
{
System.out.println(OAuthTest3
.read("http://localhost/accounts/OAuthGetRequestToken"));
}
}
private static String a64BitRandomString() {
StringBuffer sb = new StringBuffer();
Random generator = new Random();
for (int i = 0; i < 32; i++) {
Integer r = generator.nextInt();
if (r < 0) {
r = r * -1;
}
r = r % 16;
sb.append(r.toHexString(r));
}
return sb.toString();
}
private static String timeSinceEpochInMillis() {
Calendar c = Calendar.getInstance();
Date date = c.getTime();
Long time = date.getTime();
Integer i = (int) (time/1000);
return i.toString();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
应该是
m.init(new SecretKeySpec("anonymous&".getBytes(), "HmacSHA1"));
当 oauth_token_secret 为空时,仍然需要“&”将两个秘密连接起来形成完整的签名密钥。It should be
m.init(new SecretKeySpec("anonymous&".getBytes(), "HmacSHA1"));
When the oauth_token_secret is empty, you still need the "&" joining the two secrets to make the complete signature key.我建议为此使用 OAuth 库,以获得更高级别的抽象。
查看以下博客文章,了解使用 Signpost 和 j2se 进行 OAuth 交互:
http://blog.doityourselfandroid.com/2010/11/08/oauth-in-java-the-signpost-library/
博客还包含一些有关 OAuth 的其他信息。
另一件值得一提的重要事情是确保您的日期/时间设置在客户端上正确设置。当您与服务提供商交互时,如果您最终发送了错误的时间戳,您的请求将被拒绝。
I would suggest using an OAuth library for this, in order to have a higher level of abstraction.
Checkout the following blog post for an OAuth interaction using Signpost and j2se :
http://blog.doityourselfandroid.com/2010/11/08/oauth-in-java-the-signpost-library/
The blog also contains some other info regarding OAuth.
Another important thing worth mentioning is to make sure your date/time settings are setup correctly on the client. When you interact with the service provider, and you end up sending wrong timestamps, your requests will get refused.