我在this document之后获得了授权码。但是当我试图获得访问令牌时,我总是遇到错误。任何人都可以帮助我吗?
public String AccessToken()
{
String accessToken = "";
StringBuilder strBuild = new StringBuilder();
String authURL = "https://accounts.google.com/o/oauth2/token?";
String code = "4/SVisuz_x*********************";
String client_id = "******************e.apps.googleusercontent.com";
String client_secret = "*******************";
String redirect_uri = "urn:ietf:wg:oauth:2.0:oob";
String grant_type="authorization_code";
strBuild.append("code=").append(code)
.append("&client_id=").append(client_id)
.append("&client_secret=").append(client_secret)
.append("&redirect_uri=").append(redirect_uri)
.append("&grant_type=").append(grant_type);
System.out.println(strBuild.toString());
try{
URL obj = new URL(authURL);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Host", "www.googleapis.com");
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(con.getOutputStream()));
//bw.write(strBuild.toString());
//bw.close();
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(strBuild.toString());
wr.flush();
wr.close();
//OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream());
System.out.println(con.getResponseCode());
System.out.println(con.getResponseMessage());
} catch (Exception e)
{
System.out.println("Error.");
}
return "";
}
当我运行此代码时,输出为:
400
Bad Request
答案 0 :(得分:9)
如何使用gmail api获取访问令牌?
答案:根据your following tutorial,您使用的是OAuth 2.0
。因此,使用OAuth 2.0
访问Google API的基本模式。它遵循4个步骤:
有关详细信息,您可以按照教程 - Using OAuth 2.0 to Access Google APIs
进行操作您必须访问Google Developers Console以获取OAuth 2.0凭据,例如Google和您的应用程序都知道的client ID
和client secret
<强>问题-1:强>
在研究了你的代码之后,发现了一些缺乏的代码。如果代码运行顺畅,那么代码总是给出一个空字符串。因为您的AccessToken()
方法始终返回return "";
<强>问题-2:强>
catch (Exception e)
{
System.out.println("Error.");
}
你的try catch块正在进行异常阻止。因为,您似乎还没有正确完成代码。您错过了encoding
以及使用准备访问令牌的JSONObject
。所以它将输出作为
错误。
我知道您的代码与此tutorial
类似由于您的代码需要更多更改才能解决您的问题。所以我建议您使用 LinkedHashMap 或 ArrayList 。这些将提供更简单的解决方案。所以我给你2个示例代码,让你的生活更轻松。你可以选择其中任何一个。您需要更改refresh_token, client id, client secret and grant type
作为您的。{/ p>
private String getAccessToken()
{
try
{
Map<String,Object> params = new LinkedHashMap<>();
params.put("grant_type","refresh_token");
params.put("client_id",[YOUR CLIENT ID]);
params.put("client_secret",[YOUR CLIENT SECRET]);
params.put("refresh_token",[YOUR REFRESH TOKEN]);
StringBuilder postData = new StringBuilder();
for(Map.Entry<String,Object> param : params.entrySet())
{
if(postData.length() != 0)
{
postData.append('&');
}
postData.append(URLEncoder.encode(param.getKey(),"UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()),"UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
URL url = new URL("https://accounts.google.com/o/oauth2/token");
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestMethod("POST");
con.getOutputStream().write(postDataBytes);
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuffer buffer = new StringBuffer();
for (String line = reader.readLine(); line != null; line = reader.readLine())
{
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
String accessToken = json.getString("access_token");
return accessToken;
}
catch (Exception ex)
{
ex.printStackTrace();
}
return null;
}
对于访问google play android developer api ,您需要传递 先前的刷新令牌以获取访问令牌
private String getAccessToken(String refreshToken){
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://accounts.google.com/o/oauth2/token");
try
{
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
nameValuePairs.add(new BasicNameValuePair("grant_type", "refresh_token"));
nameValuePairs.add(new BasicNameValuePair("client_id", GOOGLE_CLIENT_ID));
nameValuePairs.add(new BasicNameValuePair("client_secret", GOOGLE_CLIENT_SECRET));
nameValuePairs.add(new BasicNameValuePair("refresh_token", refreshToken));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
org.apache.http.HttpResponse response = client.execute(post);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer buffer = new StringBuffer();
for (String line = reader.readLine(); line != null; line = reader.readLine())
{
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
String accessToken = json.getString("access_token");
return accessToken;
}
catch (IOException e) { e.printStackTrace(); }
return null;
}
Unable to get the subscription information from Google Play Android Developer API
Using java.net.URLConnection to fire and handle HTTP requests
希望这个samples
和resource link
可以帮助您解决问题并获取access token
的访问权。
Ans:表示查询无效。缺少父ID或请求的维度或指标组合无效。
推荐的操作:您需要对API查询进行更改才能使其正常工作。
对于
HTTP/1.1 400 Bad Request error
,您可以浏览my another answer。 它可以帮助您理解which host you need to use
以及需要应用的条件。
由于以下原因之一,令牌可能会停止工作:
revoked
访问权限。six months
。user changed passwords
和令牌包含Gmail,日历,
通讯录或环聊示波器。exceeded a certain number of token requests
。有currently a limit of 25 refresh tokens per user account per client
。如果达到限制,则创建新令牌会自动使最旧的令牌无效而不会发出警告。此限制不适用于服务帐户。
某些请求需要用户登录的身份验证步骤 使用他们的Google帐户。登录后,系统会询问用户是否 他们愿意授予您的应用程序的权限 请求。此过程称为用户同意。
如果用户授予权限,则为Google授权服务器 向您的应用程序发送访问令牌(或授权代码) 您的应用程序可用于获取访问令牌)。如果用户这样做 如果不授予权限,服务器将返回错误。
如果为Google+ API发放了访问令牌,则不会授予 访问Google通讯录API。但是,您可以发送该访问权限 对于类似的操作,多次使用令牌加入Google+ API。
访问令牌通常具有1小时的到期日期 如果您尝试使用它,您将收到错误。 Google Credential 自动处理&#34;刷新&#34;令牌,这只是意味着 获得新的访问令牌。
在安全的长期存储中保存刷新令牌并继续使用 只要它们仍然有效就可以。限制适用于数量 刷新每个客户端 - 用户组合和每个发布的令牌 所有客户的用户,这些限制是不同的。如果你的 应用程序请求足够的刷新令牌来覆盖其中一个 限制,旧的刷新令牌停止工作。
答案 1 :(得分:3)
您没有使用正确的端点。尝试将authURL
更改为https://www.googleapis.com/oauth2/v4/token
来自文档:
要发出此令牌请求,请向/ oauth2 / v4 / token端点发送HTTP POST请求
实际请求可能如下所示:
POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded
code=4/v6xr77ewYqhvHSyW6UJ1w7jKwAzu&
client_id=8819981768.apps.googleusercontent.com&
client_secret=your_client_secret&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code
参考 https://developers.google.com/identity/protocols/OAuth2InstalledApp#handlingtheresponse
答案 2 :(得分:0)
对我来说,你的请求很好,我尝试使用Curl,我还得到一个'HTTP / 1.1 400错误请求',原因是它失败'invalid_grant':
curl -X POST https://www.googleapis.com/oauth2/v4/token -d 'code=4/SVisuz_x*********************&client_id=*******************7vet.apps.googleusercontent.com&client_secret=***************&redirect_uri=https://oauth2-login-demo.appspot.com/code&grant_type=authorization_code'
我收到(HTTP / 1.1 400错误请求):
{
"error": "invalid_grant",
"error_description": "Code was already redeemed."
}
现在使用Apache的HttpClient:
URL obj = new URL(authURL);
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(authURL);
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
post.addHeader("Host", "www.googleapis.com");
post.setEntity(new StringEntity(strBuild.toString()));
HttpResponse resp = client.execute(post);
System.out.println(resp.getStatusLine());
System.out.println(EntityUtils.toString(resp.getEntity()));
我在我的控制台中看到:
HTTP/1.1 400 Bad Request
{
"error": "invalid_grant",
"error_description": "Code was already redeemed."
}
您确定您使用的代码仍然有效吗?你可以尝试新的吗?
答案 3 :(得分:0)
首先,您必须查看此页面:
https://developers.google.com/gmail/api/auth/web-server#create_a_client_id_and_client_secret
您在查询参数代码中看到的值是您必须发布到Google才能获取访问令牌的字符串。
在Web服务器收到授权代码后,它可以交换授权代码以获取访问令牌和刷新令牌。此请求是对网址https://www.googleapis.com/oauth2/v3/token的HTTPS POST POST / oauth2 / v3 / token HTTP / 1.1 content-type:application / x-www-form-urlencoded
代码= 4 / V4-CqVXkhiTkn9uapv6V0iqUmelHNnbLRr1EbErzkQw#&安培; REDIRECT_URI =安培; CLIENT_ID =安培;范围=安培; client_secret = ************&安培; grant_type = authorization_code https://developers.google.com/identity/protocols/OAuth2WebServer
答案 4 :(得分:0)
我想我明白了什么是错的:
正如@newhouse所说,你应该发帖到https://www.googleapis.com/oauth2/v4/token
而不是https://accounts.google.com/o/oauth2/token
(@newhouse我给你+1 :))
(https://www.googleapis.com/oauth2/v4/token
用于获取authorization_code
而https://accounts.google.com/o/oauth2/token
用于获取code
。
您不能多次使用相同的code
。
其他所有内容看起来都是有序的,如果你继续得到400,你可能会尝试使用你有多次的code
(那么你每次都会得到400次,一次又一次)。 / p>
*您还应该丢失con.setRequestProperty("Host", "www.googleapis.com");
答案 5 :(得分:0)
参考:https://developers.google.com/android-publisher/authorization
您已拥有名为“刷新令牌”的授权码。请妥善保管。您可以使用“刷新令牌”生成“访问令牌”。
要获取“访问令牌”,请向以下网址发送帖子请求
https://accounts.google.com/o/oauth2/token
参数:
其中“grant_type”应为“refresh_token”
我们使用PHP来做同样的事情,这里是PHP的代码供您参考
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://accounts.google.com/o/oauth2/token',
CURLOPT_USERAGENT => 'Pocket Experts Services',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => array(
"grant_type" => "refresh_token",
"client_id" => $GOOGLE_CLIENT_ID,
"client_secret" => $GOOGLE_CLIENT_SECRET,
"refresh_token" => $GOOGLE_REFRESH_TOKEN,
)));
// Send the request & save response to $resp
$resp = curl_exec($curl);
希望它会对你有所帮助。
答案 6 :(得分:0)
低安全性方法是暂时的,我无法在生产中使用它,但我发现有一篇文章使使用节点here变得更容易 带有示例代码,效果很好