API Key當(dāng)用戶注冊(cè)之后,會(huì)給用戶一個(gè)API Key。這個(gè)API Key會(huì)附在每個(gè)請(qǐng)求的url后面,這個(gè)方式的缺點(diǎn)是如果某個(gè)人知道你的API Key之后,他就能偽裝成那個(gè)用戶了。 但是如果你的API請(qǐng)求是使用HTTPS(SSL)的方式,就可以避免你的API Key被別人獲取了。
API Key + Secret Key簽名比上一種跟復(fù)雜的一種方式就是用一個(gè)secret key去簽名每一刻API URL請(qǐng)求,Amazon Web Services就是使用這種方式。當(dāng)用戶注冊(cè)完后, 你會(huì)給用戶2個(gè)keys:API Key(比如:username)和secret key(比如password),API key會(huì)附在每個(gè)請(qǐng)求url上面,但是secret key
不會(huì)。secret key是用來簽名每個(gè)請(qǐng)求的。通常會(huì)加上另外一個(gè)參數(shù)比如(Signature)。
Amazon會(huì)把所有的請(qǐng)求信息作為請(qǐng)求的參數(shù),然后按照參數(shù)名排序,再按照secret key進(jìn)行hash。這個(gè)hash的值會(huì)作為一個(gè)新的參數(shù)(Signature)附加到請(qǐng)求的url上。在server端做相同的事情,獲得所有的參數(shù)(除了Signature),排序,用sercet key hash,如果這個(gè)值跟傳過來的Signature參數(shù)的值相等的話,則認(rèn)為這個(gè)請(qǐng)求是合法的。
下面的是引用Amazon Web Services文檔中的內(nèi)容。
For example, the following is a Query string (linebreaks added for clarity).
引用
Action=DescribeImages
&AWSAccessKeyId=10QMXFEV71ZS32XQFTR2
&SignatureVersion=1
&Timestamp=2006-12-08T07%3A48%3A03Z
&Version=2007-01-03
For the preceding Query string, you would calculate the HMAC signature over the following string.
引用
(linebreaks added for clarity)
ActionDescribeImages
AWSAccessKeyId10QMXFEV71ZS32XQFTR2
SignatureVersion1
Timestamp2006-12-08T07:48:03Z
Version2007-01-03
Using the preceding string and the secret key DMADSSfPfdaDjbK+RRUhS/aDrjsiZadgAUm8gRU2 the
base64 encoded signature is as follows:
GjH3941IBe6qsgQu+k7FpCJjpnc=
The following is a Java code sample to compute the signature from the string and the private key.
引用
import java.security.SignatureException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class HmacExample
{
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
/**
* Computes RFC 2104-compliant HMAC signature.
*
* @param data
* The data to be signed.
* @param key
* The signing key.
* @return
* The base64-encoded RFC 2104-compliant HMAC signature.
* @throws
* java.security.SignatureException when signature generation fails
*/
public static String calculateRFC2104HMAC(String data, String key)
throws java.security.SignatureException
{
String result;
try {
// get an hmac_sha1 key from the raw key bytes
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(),
HMAC_SHA1_ALGORITHM);
// get an hmac_sha1 Mac instance
// and initialize with the signing key
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
// compute the hmac on input data bytes
byte[] rawHmac = mac.doFinal(data.getBytes());
// base64-encode the hmac
result = Base64.encodeBytes(rawHmac);
}
catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : "
+ e.getMessage());
}
return result;
}
}