package de.otto.hmac.authentication.jersey; import com.google.common.io.ByteSource; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.client.apache4.ApacheHttpClient4; import com.sun.jersey.client.apache4.ApacheHttpClient4Handler; import com.sun.jersey.client.apache4.config.DefaultApacheHttpClient4Config; import de.otto.hmac.HmacAttributes; import de.otto.hmac.StringUtils; import de.otto.hmac.authentication.RequestSigningUtil; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; import java.io.IOException; import java.time.Clock; import java.time.ZonedDateTime; public class HMACJerseyClient extends ApacheHttpClient4 { private String user; private String secretKey; private String method; private String date; private String requestUri; private ByteSource body = ByteSource.empty(); private final Clock clock; private HMACJerseyClient(final ClientConfig cc, final Clock clock) { super(createDefaultClientHander(cc)); this.clock = clock; } public HMACJerseyClient auth(final String user, final String secretKey) { this.user = user; this.secretKey = secretKey; return this; } public WebResource.Builder authenticatedResource(final String url) throws IOException { assertAuthentificationPossible(); date = ZonedDateTime.now(clock).toString(); final StringBuilder builder = new StringBuilder(user); builder.append(":"); builder.append(RequestSigningUtil.createRequestSignature(method, date, requestUri, body, secretKey)); return resource(url).header(HmacAttributes.X_HMAC_AUTH_SIGNATURE, builder.toString()).header( HmacAttributes.X_HMAC_AUTH_DATE, date); } private void assertAuthentificationPossible() throws IOException { validateNullOrEmpty(user); validateNullOrEmpty(secretKey); validateNullOrEmpty(method); validateNullOrEmpty(requestUri); } private void validateNullOrEmpty(String property) { if (StringUtils.isNullOrEmpty(property)) { throw new IllegalArgumentException("argument " + property + " is empty or null"); } } private static ApacheHttpClient4Handler createDefaultClientHander(final ClientConfig cc) { final HttpParams params = new BasicHttpParams(); final int maxConnections = 20; final ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(); manager.setDefaultMaxPerRoute(maxConnections); manager.setMaxTotal(maxConnections); return new ApacheHttpClient4Handler(new DefaultHttpClient(manager, params), null, false); } public static HMACJerseyClient create() { return create(Clock.systemUTC()); } public static HMACJerseyClient create(final Clock clock) { DefaultApacheHttpClient4Config config = new DefaultApacheHttpClient4Config(); return new HMACJerseyClient(config, clock); } public HMACJerseyClient withMethod(final String method) { this.method = method; return this; } public HMACJerseyClient withUri(final String uri) { this.requestUri = uri; return this; } public HMACJerseyClient withBody(final ByteSource body) { this.body = body; return this; } }