Skip to content

Instantly share code, notes, and snippets.

@ichengchao
Created December 29, 2022 12:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ichengchao/a08ff7052ea0f662b3e5c09d178e3e4c to your computer and use it in GitHub Desktop.
Save ichengchao/a08ff7052ea0f662b3e5c09d178e3e4c to your computer and use it in GitHub Desktop.
AWS API签名
package name.chengchao.springrun.util;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
public class AwsAPIAuth {
private final static String AccessKey = "***************";
private final static String SecretKey = "***************";
public static void main(String[] args) throws Exception {
listIAMUsers();
// createGroup();
}
public static void listIAMUsers() throws Exception {
String region = "us-east-1";
String httpMethod = "GET";
String url = "https://iam.amazonaws.com/";
Map<String, String> urlParams = new TreeMap<>();
urlParams.put("Action", "ListUsers");
urlParams.put("Version", "2010-05-08");
doRequest(region, httpMethod, url, urlParams, null);
}
public static void createGroup() throws Exception {
String region = "us-east-1";
String httpMethod = "POST";
String url = "https://iam.amazonaws.com/";
Map<String, String> urlParams = new TreeMap<>();
String body = "Action=CreateGroup&Version=2010-05-08&GroupName=charlesTestGroup1941";
doRequest(region, httpMethod, url, urlParams, body);
}
public static String doRequest(String region, String httpMethod, String url, Map<String, String> urlParams,
String body)
throws Exception {
// 容忍度是30分钟,+-15分钟
// Signature expired: 20221229T051026Z is now earlier than 20221229T063528Z (20221229T065028Z - 15 min.)
// Signature not yet current: 20221229T071139Z is still later than 20221229T070641Z (20221229T065141Z + 15 min.)
Calendar calendar = Calendar.getInstance();
// calendar.add(Calendar.MINUTE, 20);
Date now = calendar.getTime();
String datetime = DateFormatUtils.formatUTC(now, "yyyyMMdd'T'HHmmss'Z'");
String date = DateFormatUtils.formatUTC(now, "yyyyMMdd");
String host = new URL(url).getHost();
String service = host.substring(0, host.indexOf('.'));
Map<String, String> headerMap = new TreeMap<>();
headerMap.put("X-Amz-Date", datetime);
headerMap.put("Host", host);
// default response is xml format
// headerMap.put("Accept", "application/json");
// if ("POST".equals(httpMethod) && StringUtils.isNotBlank(body)) {
// headerMap.put("X-Amz-Content-Sha256", DigestUtils.sha256Hex(body));
// }
String headerList = headerMap.keySet().stream().map(String::toLowerCase).collect(Collectors.joining(";"));
// step1:request structure
String requestString = buildCanonicalRequest(httpMethod, url, urlParams, headerMap, body);
// step2:request structure hash (sha256Hex)
String requestHashHex = DigestUtils.sha256Hex(requestString);
// step3:string to sign
String scope = date + "/" + region + "/" + service + "/aws4_request";
String stringToSign = buildStringToSign(datetime, scope, requestHashHex);
// step4:sign code
String sign = sign(SecretKey, date, region, service, stringToSign);
// step5:authorization header
String authorization = buildAuthorization(AccessKey, scope, headerList, sign);
headerMap.put("Authorization", authorization);
System.out.println("--------------1. request structure---------------------------------");
System.out.println(requestString);
System.out.println("--------------2. request structure hash (sha256Hex)----------------");
System.out.println(requestHashHex);
System.out.println("--------------3. string to sign------------------------------------");
System.out.println(stringToSign);
System.out.println("--------------4. sign code-----------------------------------------");
System.out.println(sign);
System.out.println("--------------5. authorization header------------------------------");
System.out.println(authorization);
System.out.println("==============response=============================================");
String result = null;
if ("GET".equals(httpMethod)) {
result = OkHttpClientUtils.get(url, urlParams, headerMap);
} else if ("POST".equals(httpMethod)) {
result = OkHttpClientUtils.post(url, headerMap, body, "application/x-www-form-urlencoded");
}
System.out.println(result);
return result;
}
/**
* 第一步: 构建请求体
*
* @param httpMethod
* @param url
* @param urlParams
* @param headerMap
* @param body
* @return
* @throws Exception
*/
public static String buildCanonicalRequest(String httpMethod, String url, Map<String, String> urlParams,
Map<String, String> headerMap, String body) throws Exception {
StringBuilder sb = new StringBuilder();
sb.append(httpMethod);
sb.append("\n");
sb.append(new URL(url).getPath());
sb.append("\n");
if (urlParams != null && !urlParams.isEmpty()) {
for (Map.Entry<String, String> entry : urlParams.entrySet()) {
sb.append(entry.getKey());
sb.append("=");
sb.append(entry.getValue());
sb.append("&");
}
sb.deleteCharAt(sb.lastIndexOf("&"));
}
sb.append("\n");
if (headerMap != null && !headerMap.isEmpty()) {
String headerList = headerMap.keySet().stream().map(String::toLowerCase).collect(Collectors.joining(";"));
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
sb.append(StringUtils.lowerCase(entry.getKey()));
sb.append(":");
sb.append(entry.getValue());
sb.append("\n");
}
sb.append("\n");
sb.append(headerList);
sb.append("\n");
}
if (StringUtils.isBlank(body)) {
body = "";
}
// add sha256hex payload
sb.append(DigestUtils.sha256Hex(body));
return sb.toString();
}
/**
* 第二步: 构建签名体
*
* @param datetime
* @param scope 请求范围
* @param requestHashHex 请求体的hash摘要sha-256
* @return
*/
public static String buildStringToSign(String datetime, String scope, String requestHashHex) {
StringBuilder sb = new StringBuilder();
sb.append("AWS4-HMAC-SHA256");
sb.append("\n");
sb.append(datetime);
sb.append("\n");
sb.append(scope);
sb.append("\n");
sb.append(requestHashHex);
return sb.toString();
}
/**
* 第三步: 签名
*
* @param secretKey
* @param date
* @param region
* @param service
* @param stringToSign
* @return
* @throws Exception
*/
public static String sign(String secretKey, String date, String region, String service, String stringToSign)
throws Exception {
byte[] kSecret = ("AWS4" + secretKey).getBytes("UTF8");
byte[] kDate = HmacUtils.hmacSHA256(kSecret, date);
byte[] kRegion = HmacUtils.hmacSHA256(kDate, region);
byte[] kService = HmacUtils.hmacSHA256(kRegion, service);
byte[] kSigning = HmacUtils.hmacSHA256(kService, "aws4_request");
byte[] signByte = HmacUtils.hmacSHA256(kSigning, stringToSign);
String sign = Hex.encodeHexString(signByte);
return sign;
}
/**
* 第四步: 构建 authorization header
*
* @param accessKey
* @param scope
* @param sign
* @return
*/
public static String buildAuthorization(String accessKey, String scope, String headerList, String sign) {
StringBuilder authorizationBuilder = new StringBuilder();
authorizationBuilder.append("AWS4-HMAC-SHA256");
authorizationBuilder.append(" ");
authorizationBuilder.append("Credential=" + accessKey);
authorizationBuilder.append("/");
authorizationBuilder.append(scope);
authorizationBuilder.append(",");
authorizationBuilder.append("SignedHeaders=");
authorizationBuilder.append(headerList);
authorizationBuilder.append(",");
authorizationBuilder.append("Signature=");
authorizationBuilder.append(sign);
return authorizationBuilder.toString();
}
}
package name.chengchao.springrun.util;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* OkHttp client
*
* @author charles
*
*/
public class OkHttpClientUtils {
// public static final MediaType MediaType_JSON = MediaType.parse("application/json; charset=utf-8");
public static OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(40, TimeUnit.SECONDS)
.callTimeout(60, TimeUnit.SECONDS)
.addInterceptor(new SimpleLoggingInterceptor())
.build();
public static enum HttpMethod {
GET,
POST,
PUT,
PATCH,
DELETE
}
public static void main(String[] args) throws Exception {
String url = "https://www.chengchao.name";
System.out.println(get(url, null, null));
}
public static String get(String url, Map<String, String> urlParams, Map<String, String> headerMap)
throws Exception {
HttpUrl.Builder httpUrl = HttpUrl.parse(url).newBuilder();
if (null != urlParams && !urlParams.isEmpty()) {
for (Map.Entry<String, String> entry : urlParams.entrySet()) {
httpUrl.addQueryParameter(entry.getKey(), entry.getValue());
}
}
String result = excute(httpUrl.build(), HttpMethod.GET, headerMap, null);
return result;
}
public static String post(String url, Map<String, String> headerMap, String jsonBody)
throws Exception {
HttpUrl.Builder httpUrl = HttpUrl.parse(url).newBuilder();
String result =
excute(httpUrl.build(), HttpMethod.POST, headerMap, jsonBody, "application/json; charset=utf-8");
return result;
}
public static String post(String url, Map<String, String> headerMap, String body, String mediaType)
throws Exception {
HttpUrl.Builder httpUrl = HttpUrl.parse(url).newBuilder();
String result = excute(httpUrl.build(), HttpMethod.POST, headerMap, body, mediaType);
return result;
}
public static String post(String url, Map<String, String> headerMap, Map<String, String> formBody)
throws Exception {
HttpUrl.Builder httpUrl = HttpUrl.parse(url).newBuilder();
String result = excute(httpUrl.build(), HttpMethod.POST, headerMap, formBody);
return result;
}
public static String put(String url, Map<String, String> headerMap, String jsonBody)
throws Exception {
HttpUrl.Builder httpUrl = HttpUrl.parse(url).newBuilder();
String result = excute(httpUrl.build(), HttpMethod.PUT, headerMap, jsonBody);
return result;
}
public static String delete(String url, Map<String, String> headerMap)
throws Exception {
HttpUrl.Builder httpUrl = HttpUrl.parse(url).newBuilder();
String result = excute(httpUrl.build(), HttpMethod.DELETE, headerMap, null);
return result;
}
public static String patch(String url, Map<String, String> headerMap, String body)
throws Exception {
HttpUrl.Builder httpUrl = HttpUrl.parse(url).newBuilder();
String result = excute(httpUrl.build(), HttpMethod.PATCH, headerMap, body);
return result;
}
public static String excute(HttpUrl httpUrl, HttpMethod method, Map<String, String> headerMap, Object body)
throws Exception {
return excute(httpUrl, method, headerMap, body, null);
}
@SuppressWarnings("unchecked")
public static String excute(HttpUrl httpUrl, HttpMethod method, Map<String, String> headerMap, Object body,
String mediaType)
throws Exception {
Headers.Builder headers = new Headers.Builder();
if (null != headerMap && !headerMap.isEmpty()) {
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
headers.add(entry.getKey(), entry.getValue());
}
}
RequestBody requestBody = null;
if (null != body) {
if (body instanceof String) {
String bodyString = (String)body;
requestBody = RequestBody.create(bodyString, MediaType.parse(mediaType));
} else if (body instanceof HashMap) {
Map<String, String> bodyMap = (Map<String, String>)body;
FormBody.Builder formBody = new FormBody.Builder();
for (Map.Entry<String, String> entry : bodyMap.entrySet()) {
formBody.add(entry.getKey(), entry.getValue());
}
requestBody = formBody.build();
}
}
Request request = new Request(httpUrl, method.toString(), headers.build(), requestBody, new HashMap<>());
Call call = client.newCall(request);
Response response = call.execute();
int responseCode = response.code();
String result = response.body().string();
// 2xx 正常
if (!(200 <= responseCode && 300 > responseCode)) {
throw new RuntimeException("[" + responseCode + "] " + result);
}
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment