OAuth 1.0 "Could not authenticate you."
OAuth 1.0 "Could not authenticate you."
你好,首先这是一个推特授权。我可以登录,我可以获得时间表等。我可以得到这些东西,因为他们不需要额外的参数。但是现在我想给它添加 "tweet_mode=extended" 参数。
public String extendedtweet(String token, String secret,String id) throws IOException{
String url="https://api.twitter.com/1.1/statuses/lookup.json";
headercreator hc=new headercreator(outhconsumerkey,consumersecret,token,secret);
Map<String,String> requestparams = new HashMap<String, String>();
Log.e("id",id);
requestparams.put("id",id);
String header=hc.generateHeader("GET",url,requestparams);
Log.e("header",header);
Response response =request(url,"","GET","Authorization",header);
String jsonData=response.body().string();
JsonObject js=new Gson().fromJson(jsonData, JsonObject.class);
return js.get("full_text").getAsString();
}
当我删除
requestparams.put("id",id);
那里的行说 id 参数是 missing.That 很好,因为这告诉我问题出在 Headercreator class 上:
package com.example.twittertestvol1;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* Class to generate Oauth 1.0a header for Twitter
*
*/
@RequiresApi(api = Build.VERSION_CODES.N)
public class headercreator {
private String consumerKey;
private String consumerSecret;
private String signatureMethod;
private String token;
private String tokenSecret;
private String version;
public headercreator(String consumerKey, String consumerSecret, String token, String tokenSecret) {
this.consumerKey = consumerKey;
this.consumerSecret = consumerSecret;
this.token = token;
this.tokenSecret = tokenSecret;
this.signatureMethod = "HMAC-SHA1";
this.version = "1.0";
}
private static final String oauth_consumer_key = "oauth_consumer_key";
private static final String oauth_token = "oauth_token";
private static final String oauth_signature_method = "oauth_signature_method";
private static final String oauth_timestamp = "oauth_timestamp";
private static final String oauth_nonce = "oauth_nonce";
private static final String oauth_version = "oauth_version";
private static final String oauth_signature = "oauth_signature";
private static final String HMAC_SHA1 = "HmacSHA1";
/**
* Generates oAuth 1.0a header which can be pass as Authorization header
*
* @param httpMethod
* @param url
* @param requestParams
* @return
*/
public String generateHeader(String httpMethod, String url, Map<String, String> requestParams) {
StringBuilder base = new StringBuilder();
String nonce = getNonce();
String timestamp = getTimestamp();
String baseSignatureString = generateSignatureBaseString(httpMethod, url, requestParams, nonce, timestamp);
String signature = encryptUsingHmacSHA1(baseSignatureString);
base.append("OAuth ");
append(base, oauth_consumer_key, consumerKey);
append(base, oauth_token, token);
append(base, oauth_signature_method, signatureMethod);
append(base, oauth_timestamp, timestamp);
append(base, oauth_nonce, nonce);
append(base, oauth_version, version);
append(base, oauth_signature, signature);
base.deleteCharAt(base.length() - 1);
return base.toString();
}
/**
* Generate base string to generate the oauth_signature
*
* @param httpMethod
* @param url
* @param requestParams
* @return
*/
private String generateSignatureBaseString(String httpMethod, String url, Map<String, String> requestParams, String nonce, String timestamp) {
Map<String, String> params = new HashMap<>();
if (requestParams!=null)
{
requestParams.entrySet().forEach(entry -> {
put(params, entry.getKey(), entry.getValue());
});
}
put(params, oauth_consumer_key, consumerKey);
put(params, oauth_nonce, nonce);
put(params, oauth_signature_method, signatureMethod);
put(params, oauth_timestamp, timestamp);
put(params, oauth_token, token);
put(params, oauth_version, version);
Map<String, String> sortedParams = params.entrySet().stream().sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
StringBuilder base = new StringBuilder();
sortedParams.entrySet().forEach(entry -> {
base.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
});
base.deleteCharAt(base.length() - 1);
String baseString = httpMethod.toUpperCase() + "&" + encode(url) + "&" + encode(base.toString());
return baseString;
}
@RequiresApi(api = Build.VERSION_CODES.O)
private String encryptUsingHmacSHA1(String input) {
String secret = new StringBuilder().append(encode(consumerSecret)).append("&").append(encode(tokenSecret)).toString();
byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
SecretKey key = new SecretKeySpec(keyBytes, HMAC_SHA1);
Mac mac;
try {
mac = Mac.getInstance(HMAC_SHA1);
mac.init(key);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
return null;
}
byte[] signatureBytes = mac.doFinal(input.getBytes(StandardCharsets.UTF_8));
return new String(Base64.getEncoder().encode(signatureBytes));
}
/**
* Percentage encode String as per RFC 3986, Section 2.1
*
* @param value
* @return
*/
private String encode(String value) {
String encoded = "";
try {
encoded = URLEncoder.encode(value, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
String sb = "";
char focus;
for (int i = 0; i < encoded.length(); i++) {
focus = encoded.charAt(i);
if (focus == '*') {
sb += "%2A";
} else if (focus == '+') {
sb += "%20";
} else if (focus == '%' && i + 1 < encoded.length() && encoded.charAt(i + 1) == '7' && encoded.charAt(i + 2) == 'E') {
sb += '~';
i += 2;
} else {
sb += focus;
}
}
return sb.toString();
}
private void put(Map<String, String> map, String key, String value) {
map.put(encode(key), encode(value));
}
private void append(StringBuilder builder, String key, String value) {
builder.append(encode(key)).append("=\"").append(encode(value)).append("\",");
}
private String getNonce() {
int leftLimit = 48; // numeral '0'
int rightLimit = 122; // letter 'z'
int targetStringLength = 10;
Random random = new Random();
String generatedString = random.ints(leftLimit, rightLimit + 1).filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)).limit(targetStringLength)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
return generatedString;
}
private String getTimestamp() {
return Math.round((new Date()).getTime() / 1000.0) + "";
}
}
现在想知道是否有人告诉我我无法解决的问题在哪里。这就是
的错误代码和错误
{"errors":[{"code":32,"message":"Could not authenticate you."}]}
这是三个请求函数
private Response request(String url, String bodys, String type, String Headername, String Header) throws IOException {
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType,bodys);
Request request;
if (!Headername.equals(""))
{
if (type.equals("GET"))
{
request = new Request.Builder()
.url(url)
.method(type,null)
.addHeader(Headername,Header)
.build();
}
else{
request = new Request.Builder()
.url(url)
.method(type, body)
.addHeader(Headername,Header)
.build();
}
}
else {
request = new Request.Builder()
.url(url)
.method(type, body)
.build();
}
return client.newCall(request).execute();
}
问题在 Response response =request(url,"","GET","Authorization",header);
。
您需要在调用服务时传入请求参数,但在调用request()
方法时没有传递id
或任何其他参数。对我来说,以下代码有效:
public void getTweet() {
Map<String, String> requestParams = new HashMap<>();
String id = "1263213348000325633";
// Pass all request params for header generation
requestParams.put("id", id);
requestParams.put("tweet_mode", "extended");
String url = "https://api.twitter.com/1.1/statuses/lookup.json";
String header = generator.generateHeader(HttpMethod.GET.name(), url, requestParams);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", header);
HttpEntity<String> httpEntity = new HttpEntity<String>("body", headers);
// Pass all request params in the request
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("id", id)
.queryParam("tweet_mode", "extended");
ResponseEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, httpEntity, String.class);
String responseBody = response.getBody();
assertNotNull(responseBody);
System.out.println(responseBody);
}
可用的工作代码 here 作为一个 junit。
你好,首先这是一个推特授权。我可以登录,我可以获得时间表等。我可以得到这些东西,因为他们不需要额外的参数。但是现在我想给它添加 "tweet_mode=extended" 参数。
public String extendedtweet(String token, String secret,String id) throws IOException{
String url="https://api.twitter.com/1.1/statuses/lookup.json";
headercreator hc=new headercreator(outhconsumerkey,consumersecret,token,secret);
Map<String,String> requestparams = new HashMap<String, String>();
Log.e("id",id);
requestparams.put("id",id);
String header=hc.generateHeader("GET",url,requestparams);
Log.e("header",header);
Response response =request(url,"","GET","Authorization",header);
String jsonData=response.body().string();
JsonObject js=new Gson().fromJson(jsonData, JsonObject.class);
return js.get("full_text").getAsString();
}
当我删除
requestparams.put("id",id);
那里的行说 id 参数是 missing.That 很好,因为这告诉我问题出在 Headercreator class 上:
package com.example.twittertestvol1;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* Class to generate Oauth 1.0a header for Twitter
*
*/
@RequiresApi(api = Build.VERSION_CODES.N)
public class headercreator {
private String consumerKey;
private String consumerSecret;
private String signatureMethod;
private String token;
private String tokenSecret;
private String version;
public headercreator(String consumerKey, String consumerSecret, String token, String tokenSecret) {
this.consumerKey = consumerKey;
this.consumerSecret = consumerSecret;
this.token = token;
this.tokenSecret = tokenSecret;
this.signatureMethod = "HMAC-SHA1";
this.version = "1.0";
}
private static final String oauth_consumer_key = "oauth_consumer_key";
private static final String oauth_token = "oauth_token";
private static final String oauth_signature_method = "oauth_signature_method";
private static final String oauth_timestamp = "oauth_timestamp";
private static final String oauth_nonce = "oauth_nonce";
private static final String oauth_version = "oauth_version";
private static final String oauth_signature = "oauth_signature";
private static final String HMAC_SHA1 = "HmacSHA1";
/**
* Generates oAuth 1.0a header which can be pass as Authorization header
*
* @param httpMethod
* @param url
* @param requestParams
* @return
*/
public String generateHeader(String httpMethod, String url, Map<String, String> requestParams) {
StringBuilder base = new StringBuilder();
String nonce = getNonce();
String timestamp = getTimestamp();
String baseSignatureString = generateSignatureBaseString(httpMethod, url, requestParams, nonce, timestamp);
String signature = encryptUsingHmacSHA1(baseSignatureString);
base.append("OAuth ");
append(base, oauth_consumer_key, consumerKey);
append(base, oauth_token, token);
append(base, oauth_signature_method, signatureMethod);
append(base, oauth_timestamp, timestamp);
append(base, oauth_nonce, nonce);
append(base, oauth_version, version);
append(base, oauth_signature, signature);
base.deleteCharAt(base.length() - 1);
return base.toString();
}
/**
* Generate base string to generate the oauth_signature
*
* @param httpMethod
* @param url
* @param requestParams
* @return
*/
private String generateSignatureBaseString(String httpMethod, String url, Map<String, String> requestParams, String nonce, String timestamp) {
Map<String, String> params = new HashMap<>();
if (requestParams!=null)
{
requestParams.entrySet().forEach(entry -> {
put(params, entry.getKey(), entry.getValue());
});
}
put(params, oauth_consumer_key, consumerKey);
put(params, oauth_nonce, nonce);
put(params, oauth_signature_method, signatureMethod);
put(params, oauth_timestamp, timestamp);
put(params, oauth_token, token);
put(params, oauth_version, version);
Map<String, String> sortedParams = params.entrySet().stream().sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
StringBuilder base = new StringBuilder();
sortedParams.entrySet().forEach(entry -> {
base.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
});
base.deleteCharAt(base.length() - 1);
String baseString = httpMethod.toUpperCase() + "&" + encode(url) + "&" + encode(base.toString());
return baseString;
}
@RequiresApi(api = Build.VERSION_CODES.O)
private String encryptUsingHmacSHA1(String input) {
String secret = new StringBuilder().append(encode(consumerSecret)).append("&").append(encode(tokenSecret)).toString();
byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
SecretKey key = new SecretKeySpec(keyBytes, HMAC_SHA1);
Mac mac;
try {
mac = Mac.getInstance(HMAC_SHA1);
mac.init(key);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
return null;
}
byte[] signatureBytes = mac.doFinal(input.getBytes(StandardCharsets.UTF_8));
return new String(Base64.getEncoder().encode(signatureBytes));
}
/**
* Percentage encode String as per RFC 3986, Section 2.1
*
* @param value
* @return
*/
private String encode(String value) {
String encoded = "";
try {
encoded = URLEncoder.encode(value, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
String sb = "";
char focus;
for (int i = 0; i < encoded.length(); i++) {
focus = encoded.charAt(i);
if (focus == '*') {
sb += "%2A";
} else if (focus == '+') {
sb += "%20";
} else if (focus == '%' && i + 1 < encoded.length() && encoded.charAt(i + 1) == '7' && encoded.charAt(i + 2) == 'E') {
sb += '~';
i += 2;
} else {
sb += focus;
}
}
return sb.toString();
}
private void put(Map<String, String> map, String key, String value) {
map.put(encode(key), encode(value));
}
private void append(StringBuilder builder, String key, String value) {
builder.append(encode(key)).append("=\"").append(encode(value)).append("\",");
}
private String getNonce() {
int leftLimit = 48; // numeral '0'
int rightLimit = 122; // letter 'z'
int targetStringLength = 10;
Random random = new Random();
String generatedString = random.ints(leftLimit, rightLimit + 1).filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)).limit(targetStringLength)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
return generatedString;
}
private String getTimestamp() {
return Math.round((new Date()).getTime() / 1000.0) + "";
}
}
现在想知道是否有人告诉我我无法解决的问题在哪里。这就是
的错误代码和错误{"errors":[{"code":32,"message":"Could not authenticate you."}]}
这是三个请求函数
private Response request(String url, String bodys, String type, String Headername, String Header) throws IOException {
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType,bodys);
Request request;
if (!Headername.equals(""))
{
if (type.equals("GET"))
{
request = new Request.Builder()
.url(url)
.method(type,null)
.addHeader(Headername,Header)
.build();
}
else{
request = new Request.Builder()
.url(url)
.method(type, body)
.addHeader(Headername,Header)
.build();
}
}
else {
request = new Request.Builder()
.url(url)
.method(type, body)
.build();
}
return client.newCall(request).execute();
}
问题在 Response response =request(url,"","GET","Authorization",header);
。
您需要在调用服务时传入请求参数,但在调用request()
方法时没有传递id
或任何其他参数。对我来说,以下代码有效:
public void getTweet() {
Map<String, String> requestParams = new HashMap<>();
String id = "1263213348000325633";
// Pass all request params for header generation
requestParams.put("id", id);
requestParams.put("tweet_mode", "extended");
String url = "https://api.twitter.com/1.1/statuses/lookup.json";
String header = generator.generateHeader(HttpMethod.GET.name(), url, requestParams);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", header);
HttpEntity<String> httpEntity = new HttpEntity<String>("body", headers);
// Pass all request params in the request
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("id", id)
.queryParam("tweet_mode", "extended");
ResponseEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, httpEntity, String.class);
String responseBody = response.getBody();
assertNotNull(responseBody);
System.out.println(responseBody);
}
可用的工作代码 here 作为一个 junit。