我正在尝试使用它显示的 /admin/v1/users 创建
{
"code":40103,
"message":"Invalid signature in request credentials",
"stat":"FAIL"
}
这是我的Java代码:
public class DuoCreateUsers {
private static SortedMap<String, Object> params = new TreeMap<String, Object>();
public static void main(String[] args) throws IOException {
String ikey = "x";
String skey = "x";
String host = "api-d221a358.duosecurity.com";
String httpMethod = "POST";
String requestPath = "/admin/v1/users";
String timestamp = OffsetDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME);
String username = "newuser";
String email = "[email protected]";
params.put("username",username);
params.put("email",email);
String queryString = canonQueryString();
String canonicalRequest = timestamp + "\n" + httpMethod + "\n" + requestPath + "\n" + queryString;
System.out.println("canonicalRequest = " + canonicalRequest);
String signature = sign1(canonicalRequest, skey);
// System.out.println("signature = " + signature);
String url = "https://" + host + requestPath+"?"+queryString;
System.out.println("url = " + url);
HttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Date", timestamp);
httpPost.setHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString((ikey + ":" + signature).getBytes()));
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
httpPost.setEntity(new StringEntity(params.toString()));
// Make the request
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
String responseContent = entity != null ? EntityUtils.toString(entity) : "";
String rs = "Response Status Code: " + response.getStatusLine().getStatusCode() + "\nResponse Content:\n" + responseContent;
System.out.println("rs = " + rs);
}
public static String canonQueryString()
throws UnsupportedEncodingException {
ArrayList<String> args = new ArrayList<String>();
for (String key : params.keySet()) {
String name = URLEncoder
.encode(key, "UTF-8")
.replace("+", "%20")
.replace("*", "%2A")
.replace("%7E", "~");
String value = URLEncoder
.encode(params.get(key).toString(), "UTF-8")
.replace("+", "%20")
.replace("*", "%2A")
.replace("%7E", "~");
args.add(name + "=" + value);
}
return com.duosecurity.client.Util.join(args.toArray(), "&");
}
private static String sign1(String data, String secretKey) {
try {
// Create an HMAC-SHA1 key from the secret key
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
// Initialize the HMAC-SHA1 algorithm
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(secretKeySpec);
// Calculate the HMAC-SHA1 hash
byte[] hmacSha1Bytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
// Convert the result to a hexadecimal string
String hmacSha1Hex = bytesToHex(hmacSha1Bytes);
// Print the HMAC-SHA1 hash
System.out.println("HMAC-SHA1: " + hmacSha1Hex);
return hmacSha1Hex;
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
// Helper method to convert bytes to a hexadecimal string
private static String bytesToHex(byte[] bytes) {
StringBuilder hexStringBuilder = new StringBuilder();
for (byte b : bytes) {
hexStringBuilder.append(String.format("%02x", b));
}
return hexStringBuilder.toString();
}
}
我的代码有什么问题?
请帮助我...
下面的代码对我有用
生成请求代码的签名
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
@Service
@Slf4j
public class GenerateHMACSignature {
public String generateTheToken(String canonicalString, String ikey, String skey) {
return getAPISignature(canonicalString,ikey,skey);
}
public String getAPISignature(String url,String ikey,String skey) {
Mac sha1Hmac = null;
try {
sha1Hmac = Mac.getInstance("HmacSHA1");
SecretKeySpec secretKey = new SecretKeySpec(skey.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
sha1Hmac.init(secretKey);
} catch (NoSuchAlgorithmException | InvalidKeyException | IllegalArgumentException e) {
// log.error("error in");
return StringUtils.EMPTY;
}
byte[] signatureBytes = sha1Hmac.doFinal(url.getBytes(StandardCharsets.UTF_8));
String signature= Hex.encodeHexString(signatureBytes);
String auth = ikey + ":" + signature;
System.out.println(Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8)));
return Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
}
}
用于创建用户代码
import com.ciscoduo.bulkgenerator.model.CiscoDuoCreateUserResponse;
import com.ciscoduo.bulkgenerator.utilies.GenerateHMACSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service
public class CreateUser {
private SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
private String currentTime = dateFormat.format(new Date());
@Autowired
private GenerateHMACSignature generateSignature;
private RestTemplate restTemplate = new RestTemplate();
public CiscoDuoCreateUserResponse createUser(String username) throws Exception {
String ikey = "DIEZT523RM4GZ4ETBJBQ";
String skey = "3z9e75OxFp7TuxzHJDWtctntsp2hu0UlkRgr9VxQ";
String url = String.format("https://api-43c07036.duosecurity.com/admin/v1/users?username=%s", username);
URL apiUrl=new URL(url);
String canonicalString = String.join("\n",currentTime,"POST",apiUrl.getHost(),apiUrl.getPath(),apiUrl.getQuery());
System.out.println(canonicalString);
String token = generateSignature.generateTheToken(canonicalString, ikey,skey);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Authorization", "Basic " + token);
headers.set(HttpHeaders.DATE, currentTime);
HttpEntity<Object> entity = new HttpEntity<>(headers);
ResponseEntity<CiscoDuoCreateUserResponse> ciscoDuoResponse = restTemplate.
exchange(url, HttpMethod.POST, entity, CiscoDuoCreateUserResponse.class);
return ciscoDuoResponse.getBody();
}
}
主要课程是
import com.ciscoduo.bulkgenerator.service.CreateUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.URL;
@SpringBootApplication
public class BulkgeneratorApplication implements CommandLineRunner {
@Autowired
private CreateUser createUser;
public static void main(String[] args) {
SpringApplication.run(BulkgeneratorApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}
createUser.createUser("john");
}
}