diff --git a/pom.xml b/pom.xml
index 62809a7..9624365 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
org.tomitribe
oss-parent
- 2
+ 5
tomitribe-http-signatures
@@ -42,6 +42,12 @@
+
+ org.apache.tomcat
+ tomcat-servlet-api
+ 8.5.5
+ provided
+
junit
junit
diff --git a/src/main/java/org/tomitribe/auth/signatures/HeaderReader.java b/src/main/java/org/tomitribe/auth/signatures/HeaderReader.java
new file mode 100644
index 0000000..334a5c4
--- /dev/null
+++ b/src/main/java/org/tomitribe/auth/signatures/HeaderReader.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.tomitribe.auth.signatures;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.TreeMap;
+
+public interface HeaderReader {
+ String read(String header);
+
+ class Servlet implements HeaderReader {
+ private final HttpServletRequest request;
+
+ public Servlet(final HttpServletRequest request) {
+ this.request = request;
+ }
+
+ @Override
+ public String read(final String header) {
+ return request.getHeader(header);
+ }
+ }
+
+ class Map implements HeaderReader {
+ private final java.util.Map delegate;
+
+ public Map(final java.util.Map source) {
+ this.delegate = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ this.delegate.putAll(source);
+ }
+
+ @Override
+ public String read(final String header) {
+ return delegate.get(header);
+ }
+ }
+}
diff --git a/src/main/java/org/tomitribe/auth/signatures/Signatures.java b/src/main/java/org/tomitribe/auth/signatures/Signatures.java
index 0f77a2c..85521fa 100644
--- a/src/main/java/org/tomitribe/auth/signatures/Signatures.java
+++ b/src/main/java/org/tomitribe/auth/signatures/Signatures.java
@@ -17,25 +17,24 @@
package org.tomitribe.auth.signatures;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
+import java.util.Locale;
public enum Signatures {
;
- public static String createSigningString(final List required, String method, final String uri, Map headers) {
+ private static final String REQUEST_TARGET = "(request-target)";
+
+ public static String createSigningString(final List required, String method, final String uri, final HeaderReader headers) {
method = lowercase(method);
- headers = lowercase(headers);
final List list = new ArrayList(required.size());
-
for (final String key : required) {
- if ("(request-target)".equals(key)) {
+ if (REQUEST_TARGET.equals(key)) {
list.add(Join.join(" ", "(request-target):", method, uri));
} else {
- final String value = headers.get(key);
+ final String value = headers.read(key);
if (value == null) throw new MissingRequiredHeaderException(key);
list.add(key + ": " + value);
@@ -45,16 +44,7 @@ public static String createSigningString(final List required, String met
return Join.join("\n", list);
}
- private static Map lowercase(final Map headers) {
- final Map map = new HashMap();
- for (final Map.Entry entry : headers.entrySet()) {
- map.put(entry.getKey().toLowerCase(), entry.getValue());
- }
-
- return map;
- }
-
private static String lowercase(final String spec) {
- return spec.toLowerCase();
+ return spec.toLowerCase(Locale.ENGLISH);
}
}
diff --git a/src/main/java/org/tomitribe/auth/signatures/Signer.java b/src/main/java/org/tomitribe/auth/signatures/Signer.java
index 3426f3f..45f505f 100644
--- a/src/main/java/org/tomitribe/auth/signatures/Signer.java
+++ b/src/main/java/org/tomitribe/auth/signatures/Signer.java
@@ -75,16 +75,18 @@ public Signer(final Key key, final Signature signature, final Provider provider)
sign.sign("validation".getBytes());
} catch (final RuntimeException e) {
-
- throw (RuntimeException) e;
-
+ throw e;
} catch (final Exception e) {
-
throw new IllegalStateException("Can't initialise the Signer using the provided algorithm and key", e);
}
}
+ @Deprecated // use sign(String, String, HeaderReader headers)
public Signature sign(final String method, final String uri, final Map headers) throws IOException {
+ return sign(method, uri, new HeaderReader.Map(headers));
+ }
+
+ public Signature sign(final String method, final String uri, final HeaderReader headers) throws IOException {
final String signingString = createSigningString(method, uri, headers);
@@ -97,7 +99,12 @@ public Signature sign(final String method, final String uri, final Map headers) throws IOException {
+ return createSigningString(method, uri, new HeaderReader.Map(headers));
+ }
+
+ public String createSigningString(final String method, final String uri, final HeaderReader headers) throws IOException {
return Signatures.createSigningString(signature.getHeaders(), method, uri, headers);
}
diff --git a/src/test/java/org/tomitribe/auth/signatures/SignerTest.java b/src/test/java/org/tomitribe/auth/signatures/SignerTest.java
index 21c9895..15aabd7 100644
--- a/src/test/java/org/tomitribe/auth/signatures/SignerTest.java
+++ b/src/test/java/org/tomitribe/auth/signatures/SignerTest.java
@@ -90,7 +90,7 @@ public void testSign() throws Exception {
headers.put("Digest", "SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=");
headers.put("Accept", "*/*");
headers.put("Content-Length", "18");
- final Signature signed = signer.sign(method, uri, headers);
+ final Signature signed = signer.sign(method, uri, new HeaderReader.Map(headers));
assertEquals("yT/NrPI9mKB5R7FTLRyFWvB+QLQOEAvbGmauC0tI+Jg=", signed.getSignature());
}
@@ -104,7 +104,7 @@ public void testSign() throws Exception {
headers.put("Digest", "SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=");
headers.put("Accept", "*/*");
headers.put("Content-Length", "18");
- final Signature signed = signer.sign(method, uri, headers);
+ final Signature signed = signer.sign(method, uri, new HeaderReader.Map(headers));
assertEquals("DPIsA/PWeYjySmfjw2P2SLJXZj1szDOei/Hh8nTcaPo=", signed.getSignature());
}
@@ -118,7 +118,7 @@ public void testSign() throws Exception {
headers.put("Digest", "SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu8DBPE=");
headers.put("Accept", "*/*");
headers.put("Content-Length", "18");
- final Signature signed = signer.sign(method, uri, headers);
+ final Signature signed = signer.sign(method, uri, new HeaderReader.Map(headers));
assertEquals("DPIsA/PWeYjySmfjw2P2SLJXZj1szDOei/Hh8nTcaPo=", signed.getSignature());
}
@@ -132,7 +132,7 @@ public void testSign() throws Exception {
headers.put("Digest", "SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu8DBPE=");
headers.put("Accept", "*/*");
headers.put("Content-Length", "18");
- final Signature signed = signer.sign(method, uri, headers);
+ final Signature signed = signer.sign(method, uri, new HeaderReader.Map(headers));
assertEquals("IWTDxmOoEJI67YxY3eDIRzxrsAtlYYCuGZxKlkUSYdA=", signed.getSignature());
}
}
@@ -148,7 +148,7 @@ public void defaultHeaderList() throws Exception {
final Map headers = new HashMap();
headers.put("Date", "Tue, 07 Jun 2014 20:51:35 GMT");
- final Signature signed = signer.sign("GET", "/foo/Bar", headers);
+ final Signature signed = signer.sign("GET", "/foo/Bar", new HeaderReader.Map(headers));
assertEquals("WbB9VXuVdRt1LKQ5mDuT+tiaChn8R7WhdAWAY1lhKZQ=", signed.getSignature());
}
@@ -156,7 +156,7 @@ public void defaultHeaderList() throws Exception {
final Map headers = new HashMap();
headers.put("Date", "Tue, 07 Jun 2014 20:51:36 GMT");
- final Signature signed = signer.sign("GET", "/foo/Bar", headers);
+ final Signature signed = signer.sign("GET", "/foo/Bar", new HeaderReader.Map(headers));
assertEquals("kRkh0bV1wKZSXBgexUB+zlPU88/za5K/gk/F0Aikg7Q=", signed.getSignature());
}
@@ -168,7 +168,7 @@ public void defaultHeaderList() throws Exception {
headers.put("Accept", "*/*");
headers.put("Content-Length", "18");
- final Signature signed = signer.sign("GET", "/foo/Bar", headers);
+ final Signature signed = signer.sign("GET", "/foo/Bar", new HeaderReader.Map(headers));
assertEquals("kRkh0bV1wKZSXBgexUB+zlPU88/za5K/gk/F0Aikg7Q=", signed.getSignature());
}
}
@@ -181,7 +181,7 @@ public void missingDefaultHeader() throws Exception {
final Signer signer = new Signer(key, signature);
final Map headers = new HashMap();
- signer.sign("GET", "/foo/Bar", headers);
+ signer.sign("GET", "/foo/Bar", new HeaderReader.Map(headers));
}
@Test(expected = MissingRequiredHeaderException.class)