Java 如何使用HMACSHA1和密钥创建签名以连接到Kayako API
我正在尝试使用ApacheCommonsHTTP客户端连接到第三方应用程序API。我尝试连接的API是 API要求我传递API密钥和签名以及用于创建签名的salt 根据API文档,以下是创建签名的步骤Java 如何使用HMACSHA1和密钥创建签名以连接到Kayako API,java,encryption,Java,Encryption,我正在尝试使用ApacheCommonsHTTP客户端连接到第三方应用程序API。我尝试连接的API是 API要求我传递API密钥和签名以及用于创建签名的salt 根据API文档,以下是创建签名的步骤 import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import jav
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.util.encoders.Base64Encoder;
public class GenSign2 {
public static void main(String[] args) throws GeneralSecurityException,
IOException {
String secretKey = "M2Y2YjkxZDEtYmNlOC1mYmI0LTkxZTgtOTNiY2RiMDhmN2E2YjExNGUwYjktNGJkYy1jZTM0LWQ1MWYtZGIwYWRlZTE0NGNh";
String salt = "0123456789";
String generateHmacSHA256Signature = generateHmacSHA256Signature(salt,
secretKey);
System.out.println("Signature: " + generateHmacSHA256Signature);
String urlEncodedSign = URLEncoder.encode(generateHmacSHA256Signature,
"UTF-8");
System.out.println("Url encoded value: " + urlEncodedSign);
}
public static String generateHmacSHA256Signature(String data, String key)
throws GeneralSecurityException, IOException {
byte[] hmacData = null;
try {
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"),
"HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
hmacData = mac.doFinal(data.getBytes("UTF-8"));
ByteArrayOutputStream bout = new ByteArrayOutputStream();
new Base64Encoder().encode(hmacData, 0, hmacData.length, bout);
return bout.toString("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new GeneralSecurityException(e);
}
}
}
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.util.encoders.Base64Encoder;
public class GenSign2 {
public static void main(String[] args) throws GeneralSecurityException,
IOException {
String secretKey = "M2Y2YjkxZDEtYmNlOC1mYmI0LTkxZTgtOTNiY2RiMDhmN2E2YjExNGUwYjktNGJkYy1jZTM0LWQ1MWYtZGIwYWRlZTE0NGNh";
String salt = "0123456789";
String generateHmacSHA256Signature = generateHmacSHA256Signature(salt,
secretKey);
System.out.println("Signature: " + generateHmacSHA256Signature);
String urlEncodedSign = URLEncoder.encode(generateHmacSHA256Signature,
"UTF-8");
System.out.println("Url encoded value: " + urlEncodedSign);
}
public static String generateHmacSHA256Signature(String data, String key)
throws GeneralSecurityException, IOException {
byte[] hmacData = null;
try {
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"),
"HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
hmacData = mac.doFinal(data.getBytes("UTF-8"));
ByteArrayOutputStream bout = new ByteArrayOutputStream();
new Base64Encoder().encode(hmacData, 0, hmacData.length, bout);
return bout.toString("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new GeneralSecurityException(e);
}
}
}
测试api如下所示
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
public class TestApi {
public static void main(String[] args) throws ClientProtocolException,
IOException, URISyntaxException {
HttpClient client = new DefaultHttpClient();
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("apikey",
"f165dc40-ce3f-6864-7d5e-27a7188b2e62"));
qparams.add(new BasicNameValuePair("salt", "0123456789"));
qparams.add(new BasicNameValuePair("signature", "mbrhpXkP0LzNMNDygHAorqMx%2FDGovl%2FauMTOMB6RNMA%3D"));
HttpPost httpget = new HttpPost(
"http://aruntest.kayako.com/api/index.php?e=/Core/Test");
HttpResponse response = client.execute(httpget);
System.out.println(response.getProtocolVersion());
System.out.println(response.getStatusLine().getStatusCode());
System.out.println(response.getStatusLine().getReasonPhrase());
System.out.println(response.getStatusLine().toString());
}
}
import java.io.IOException;
导入java.net.URISyntaxException;
导入java.util.ArrayList;
导入java.util.List;
导入org.apache.http.HttpResponse;
导入org.apache.http.NameValuePair;
导入org.apache.http.client.ClientProtocolException;
导入org.apache.http.client.HttpClient;
导入org.apache.http.client.methods.HttpPost;
导入org.apache.http.impl.client.DefaultHttpClient;
导入org.apache.http.message.BasicNameValuePair;
公共类测试{
公共静态void main(字符串[]args)抛出ClientProtocolException,
IOException,URISyntaxException{
HttpClient=new DefaultHttpClient();
List qparams=new ArrayList();
添加(新的BasicNameValuePair(“apikey”),
“f165dc40-ce3f-6864-7d5e-27a7188b2e62”);
添加(新的BasicNameValuePair(“salt”,“0123456789”);
qparams.add(新的BasicNameValuePair(“签名”、“mbrhpXkP0LzNMNDygHAorqMx%2FDGovl%2FauMTOMB6RNMA%3D”);
HttpPost httpget=新的HttpPost(
"http://aruntest.kayako.com/api/index.php?e=/Core/Test");
HttpResponse response=client.execute(httpget);
System.out.println(response.getProtocolVersion());
System.out.println(response.getStatusLine().getStatusCode());
System.out.println(response.getStatusLine().getReasonPhrase());
System.out.println(response.getStatusLine().toString());
}
}
演示站点可以使用
URL:用户:admin
密码:ty386rhjzz
当我尝试连接时,它会引发未经授权的访问异常。尝试将您的签名方法与此进行比较(它有效) 该调用的结果将是属性签名的值
String signature = generateHmacSHA256Signature(salt, key);
qparams.add(new BasicNameValuePair("signature", signature));
生成salt/nonce的简单方法
String nonce = String.valueOf(System.currentTimeMillis());
请参见我认为整个
getSaltedKey()
例程是不必要的。您只需使用HMAC对salt(应称为a)进行签名,并使用提供的密钥进行签名,看起来您不需要对密钥+salt进行签名。Kayako已使用一个新的文件更新了他们的文档,该文件运行良好。在创建签名的四个步骤中,我看不到任何关于您试图签署的数据的引用。获取了实际API文档的URL吗?:)我想您第一次调用System.arraycopy()
时遇到了问题--似乎您正在复制0
字节。尝试在第一次调用中交换salt.length
和0
,看看这是否能改善情况。@sarnold我正在尝试连接到卓越,谢谢链接。sun.misc.BASE64Encoder
。你可以使用任何你想要的风格。@GregS,还有其他有效的Base64类是JDK的一部分吗?@Elite Gentle:据我所知,你要么自己编写,要么使用第三方实现。为Sun(现在的Oracle)的这一事实感到羞耻,但您永远不应该使用Sun.*类。它们可能不在下一次更新中,也可能不在IBM运行时或其他程序中,等等。如果您使用它们,您的代码就不被视为纯Java。@GregS,是的,因此我前面说过,您可以使用任何您想要的味道。我刚刚演示了如何创建HMAC-SHA256签名。@精英绅士:我毫不怀疑你能理解,但你必须想到孩子们!他们会在不知道后果的情况下复制粘贴。