【问题标题】:How to get an OAuth Request Token for Google using java如何使用 java 获取 Google 的 OAuth 请求令牌
【发布时间】:2011-08-06 03:47:51
【问题描述】:

我在尝试访问 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%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

为了调试正在发送的请求,我在 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();
}
}

【问题讨论】:

    标签: java oauth google-api


    【解决方案1】:

    我建议为此使用 OAuth 库,以便获得更高级别的抽象。

    查看以下博客文章,了解使用 Signpost 和 j2se 进行 OAuth 交互:

    http://blog.doityourselfandroid.com/2010/11/08/oauth-in-java-the-signpost-library/

    该博客还包含有关 OAuth 的其他一些信息。

    另一件值得一提的重要事情是确保您的日期/时间设置在客户端上正确设置。当您与服务提供商交互并最终发送错误的时间戳时,您的请求将被拒绝。

    【讨论】:

    • 感谢您的回答,如果我周末有时间尝试一下,我会接受这个,毫无疑问它会奏效的。但是,我打算以艰难的方式来提高透明度并更好地理解流程。
    【解决方案2】:

    应该是m.init(new SecretKeySpec("anonymous&amp;".getBytes(), "HmacSHA1")); 当oauth_token_secret为空时,仍然需要将两个secret用“&”连接起来,才能构成完整的签名密钥。

    【讨论】:

    • 成功了!非常感谢。那么这只是在进行匿名身份验证时吗?
    • 不,当使用 HMAC-SHA1 作为签名协议时,它在所有情况下都使用。
    猜你喜欢
    • 2011-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 2013-05-30
    相关资源
    最近更新 更多