All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.twonote.rgwadmin4j.impl.S3Auth Maven / Gradle / Ivy

There is a newer version: 2.0.9
Show newest version
package org.twonote.rgwadmin4j.impl;

import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableSet;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.Map;
import java.util.Set;

/**
 * AWS authentication for Amazon S3 for the wonderful java okhttp client
 *
 * 

The auth class that implements okhttp's Interceptor. It adds the Date and the Authorization * header seamlessly according to your request. Usage: * *

{@code
 * OkHttpClient client = new OkHttpClient.Builder()
 * .addInterceptor(new S3Auth())
 * .build();
 * Request request = new Request.Builder()
 * .url("http://www.publicobject.com/helloworld.txt")
 * .header("User-Agent", "OkHttp Example")
 * .build();
 * Response response = client.newCall(request).execute();
 * response.body().close();
 * }
* *

Inspired by https://github.com/tax/python-requests-aws Created by hrchu on 2017/3/22. */ class S3Auth implements Interceptor { private final String accessKey; private final String secretKey; /* The subResources that must be included when constructing the CanonicalizedResource Element are acl, lifecycle, location, logging, notification, partNumber, policy, requestPayment, torrent, uploadId, uploads, versionId, versioning, versions, and website. */ private final Set subResources = ImmutableSet.of( "acl", "lifecycle", "location", "logging", "notification", "partNumber", "policy", "requestPayment", "torrent", "uploadId", "uploads", "versionId", "versioning", "versions", "website"); /* If the request specifies query string parameters overriding the response header values (see Get Object), append the query string parameters and their values. When signing, you do not encode these values; however, when making the request, you must encode these parameter values. The query string parameters in a GET request include response-content-type, response-content-language, response-expires, response-cache-control, response-content-disposition, and response-content-encoding. */ // TODO: implement this Set queryStrings = ImmutableSet.of( "response-content-type", "response-content-language", "response-expires", "response-cache-control", "response-content-disposition", "response-content-encoding"); public S3Auth(String accessKey, String secretKey) { this.accessKey = accessKey; this.secretKey = secretKey; } private static String encodeBase64(byte[] data) { String base64 = Base64.getEncoder().encodeToString(data); if (base64.endsWith("\r\n")) base64 = base64.substring(0, base64.length() - 2); if (base64.endsWith("\n")) base64 = base64.substring(0, base64.length() - 1); return base64; } @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request request = chain.request(); String httpVerb = request.method(); String date = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneId.of("GMT"))); String resource = request.url().encodedPath(); try { String subresource = request.url().queryParameterName(0); if (subResources.contains(subresource)) { resource += "?" + subresource; } } catch (Exception e) { // not match, do nothing here. } String sign = sign(httpVerb, date, resource); request = request.newBuilder().header("Authorization", sign).header("Date", date).build(); return chain.proceed(request); } private String sign(String httpVerb, String date, String resource) { return sign(httpVerb, "", "", date, resource, null); } private String sign( String httpVerb, String contentMD5, String contentType, String date, String resource, Map metas) { StringBuilder stringToSign = new StringBuilder( httpVerb + "\n" + CharMatcher.whitespace().trimFrom(contentMD5) + "\n" + CharMatcher.whitespace().trimFrom(contentType) + "\n" + date + "\n"); if (metas != null) { for (Map.Entry entity : metas.entrySet()) { stringToSign .append(CharMatcher.whitespace().trimFrom(entity.getKey())) .append(":") .append(CharMatcher.whitespace().trimFrom(entity.getValue())) .append("\n"); } } stringToSign.append(resource); try { Mac mac = Mac.getInstance("HmacSHA1"); byte[] keyBytes = secretKey.getBytes("UTF8"); SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1"); mac.init(signingKey); byte[] signBytes = mac.doFinal(stringToSign.toString().getBytes("UTF8")); String signature = encodeBase64(signBytes); return "AWS" + " " + accessKey + ":" + signature; } catch (Exception e) { throw new RuntimeException("MAC CALC FAILED."); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy