在 IMS Emulator ( http://ltiapps.net/test/tc.php ) 中单击“保存数据”,使用自动填充的数据生成 outh_signature 并将其作为隐藏值放入窗体 frmLaunch(name='frmLaunch ') 形式。我需要以编程方式生成类似的 outh_signature,但即使我使用相同的 oauth_nounce 和 oauth_timestamp,我也无法生成模拟器生成的确切 oauth_signature。我不确定生成时需要发送的请求正文是什么签名..
要重新创建场景,请按照以下步骤操作
- 点击网址http://ltiapps.net/test/tc.php
- 单击清除数据,然后在弹出窗口中单击确定
- 选择角色作为学习者,然后单击保存数据
保存数据后,您将看到一个 outh_signature 隐藏值,输入 id 为“oauth_signature”
我尝试以以下方式生成,但无法获得预期的签名。
import java.io.*; import java.net.URL; import java.net.URLEncoder; import java.util.LinkedHashMap; import java.util.Map; import java.util.TreeMap; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.HttpsURLConnection; // Apache Commons Libraries used for the Nonce & Base64 import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; public class OAuthTest { public static void main(final String[] args) throws Exception { // Setup the variables necessary to create the OAuth 1.0 signature and make the request String httpMethod = "POST"; String consumerKey = "jisc.ac.uk"; String secret = "secret"; String signatureMethod = "HMAC-SHA1"; String body = ""; //mentioned in the description byte[] requestBody = null; URL url = new URL("http://ltiapps.net/test/tp.php"); // Set the Nonce and Timestamp parameters String nonce = "6d95eef168e568a530d1cd419a997952";//getNonce(); String timestamp = "1483470400";//getTimestamp(); System.out.println("Nonce:" + getNonce()); System.out.println("timestamp:" + getTimestamp()); // Set the request body if making a POST or PUT request if ("POST".equals(httpMethod) || "PUT".equals(httpMethod)) { requestBody = body.getBytes("UTF-8"); } // Create the OAuth parameter name/value pair Map<String, String> oauthParams = new LinkedHashMap<String, String>(); oauthParams.put("oauth_consumer_key", consumerKey); oauthParams.put("oauth_signature_method", signatureMethod); oauthParams.put("oauth_timestamp", timestamp); oauthParams.put("oauth_nonce", nonce); // Get the OAuth 1.0 Signature String signature = generateSignature(httpMethod, url, oauthParams, requestBody, secret); System.out.println(String.format("OAuth 1.0 Signature: %s", signature)); } private static String getNonce() { return RandomStringUtils.randomAlphanumeric(32); } private static String getTimestamp() { return Long.toString((System.currentTimeMillis() / 1000)); } private static String generateSignature( String httpMethod, URL url, Map<String, String> oauthParams, byte[] requestBody, String secret ) throws UnsupportedEncodingException { // Ensure the HTTP Method is upper-cased httpMethod = httpMethod.toUpperCase(); // Construct the URL-encoded OAuth parameter portion of the signature base string String encodedParams = normalizeParams(httpMethod, url, oauthParams, requestBody); // URL-encode the relative URL String encodedUri = URLEncoder.encode(url.getPath(), "UTF-8"); // Build the signature base string to be signed with the Consumer Secret String baseString = String.format("%s&%s&%s", httpMethod, encodedUri, encodedParams); return hmacSha1(baseString, secret); } private static String normalizeParams( String httpMethod, URL url, Map<String, String> oauthParams, byte[] requestBody ) throws UnsupportedEncodingException { // Sort the parameters in lexicographical order, 1st by Key then by Value Map<String, String> kvpParams = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER); kvpParams.putAll(oauthParams); // Place any query string parameters into a key value pair using equals ("=") to mark // the key/value relationship and join each parameter with an ampersand ("&") if (url.getQuery() != null) { for(String keyValue : url.getQuery().split("&")) { String[] p = keyValue.split("="); kvpParams.put(p[0],p[1]); } } // Include the body parameter if dealing with a POST or PUT request if ("POST".equals(httpMethod) || "PUT".equals(httpMethod)) { String body = Base64.encodeBase64String(requestBody).replaceAll("\r\n", ""); // url encode the body 2 times now before combining other params body = URLEncoder.encode(body, "UTF-8"); body = URLEncoder.encode(body, "UTF-8"); kvpParams.put("body", body); } // separate the key and values with a "=" // separate the kvp with a "&" StringBuilder combinedParams = new StringBuilder(); String delimiter=""; for(String key : kvpParams.keySet()) { combinedParams.append(delimiter); combinedParams.append(key); combinedParams.append("="); combinedParams.append(kvpParams.get(key)); delimiter="&"; } // url encode the entire string again before returning return URLEncoder.encode(combinedParams.toString(), "UTF-8"); } public static String hmacSha1(String value, String key) { String algorithm = "HmacSHA1"; try { // Get an hmac_sha1 key from the raw key bytes byte[] keyBytes = key.getBytes(); SecretKeySpec signingKey = new SecretKeySpec(keyBytes, algorithm); // Get an hmac_sha1 Mac instance and initialize with the signing key Mac mac = Mac.getInstance(algorithm); mac.init(signingKey); // Compute the hmac on input data bytes // byte[] rawHmac = mac.doFinal(value.getBytes()); // Convert raw bytes to Hex // byte[] hexBytes = new Hex().encode(rawHmac); return new String(Base64.encodeBase64(mac.doFinal(value.getBytes()))).trim(); // Covert array of Hex bytes to a String //return new String(hexBytes, "UTF-8"); } catch (Exception e) { throw new RuntimeException(e); } } }
pom.xml
<dependencies> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.0</version> </dependency>
我通过发送如下请求正文尝试了上述程序,并获得了 oauth 签名为 0YI3mBg7gmnWaz8YyISG4IoHVQ4=但预期是yuuvR1pVDm5xWOYhMtBcBBVTdf8=
你能告诉我我哪里出错了..