refactor SignatureUtils and related usage (#10291)
This commit is contained in:
parent
92bf15dee2
commit
dea2498718
|
|
@ -38,12 +38,11 @@ public class AccessKeyAuthenticator implements Authenticator {
|
|||
@Override
|
||||
public void sign(Invocation invocation, URL url) {
|
||||
String currentTime = String.valueOf(System.currentTimeMillis());
|
||||
String consumer = url.getApplication();
|
||||
AccessKeyPair accessKeyPair = getAccessKeyPair(invocation, url);
|
||||
invocation.setAttachment(Constants.REQUEST_SIGNATURE_KEY, getSignature(url, invocation, accessKeyPair.getSecretKey(), currentTime));
|
||||
invocation.setAttachment(Constants.REQUEST_TIMESTAMP_KEY, currentTime);
|
||||
invocation.setAttachment(Constants.AK_KEY, accessKeyPair.getAccessKey());
|
||||
invocation.setAttachment(CommonConstants.CONSUMER, consumer);
|
||||
invocation.setAttachment(CommonConstants.CONSUMER, url.getApplication());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -52,12 +51,11 @@ public class AccessKeyAuthenticator implements Authenticator {
|
|||
String requestTimestamp = String.valueOf(invocation.getAttachment(Constants.REQUEST_TIMESTAMP_KEY));
|
||||
String originSignature = String.valueOf(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY));
|
||||
String consumer = String.valueOf(invocation.getAttachment(CommonConstants.CONSUMER));
|
||||
|
||||
if (StringUtils.isEmpty(accessKeyId) || StringUtils.isEmpty(consumer)
|
||||
|| StringUtils.isEmpty(requestTimestamp) || StringUtils.isEmpty(originSignature)) {
|
||||
throw new RpcAuthenticationException("Failed to authenticate, maybe consumer not enable the auth");
|
||||
if (StringUtils.isAnyEmpty(accessKeyId, consumer, requestTimestamp, originSignature)) {
|
||||
throw new RpcAuthenticationException("Failed to authenticate, maybe consumer side did not enable the auth");
|
||||
}
|
||||
AccessKeyPair accessKeyPair = null;
|
||||
|
||||
AccessKeyPair accessKeyPair;
|
||||
try {
|
||||
accessKeyPair = getAccessKeyPair(invocation, url);
|
||||
} catch (Exception e) {
|
||||
|
|
@ -75,10 +73,10 @@ public class AccessKeyAuthenticator implements Authenticator {
|
|||
AccessKeyStorage accessKeyStorage = applicationModel.getExtensionLoader(AccessKeyStorage.class)
|
||||
.getExtension(url.getParameter(Constants.ACCESS_KEY_STORAGE_KEY, Constants.DEFAULT_ACCESS_KEY_STORAGE));
|
||||
|
||||
AccessKeyPair accessKeyPair = null;
|
||||
AccessKeyPair accessKeyPair;
|
||||
try {
|
||||
accessKeyPair = accessKeyStorage.getAccessKey(url, invocation);
|
||||
if (accessKeyPair == null || StringUtils.isEmpty(accessKeyPair.getAccessKey()) || StringUtils.isEmpty(accessKeyPair.getSecretKey())) {
|
||||
if (accessKeyPair == null || StringUtils.isAnyEmpty(accessKeyPair.getAccessKey(), accessKeyPair.getSecretKey())) {
|
||||
throw new AccessKeyNotFoundException("AccessKeyId or secretAccessKey not found");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
@ -88,16 +86,11 @@ public class AccessKeyAuthenticator implements Authenticator {
|
|||
}
|
||||
|
||||
String getSignature(URL url, Invocation invocation, String secretKey, String time) {
|
||||
String requestString = String.format(Constants.SIGNATURE_STRING_FORMAT, url.getColonSeparatedKey(), invocation.getMethodName(), secretKey, time);
|
||||
boolean parameterEncrypt = url.getParameter(Constants.PARAMETER_SIGNATURE_ENABLE_KEY, false);
|
||||
String signature;
|
||||
String requestString = String.format(Constants.SIGNATURE_STRING_FORMAT,
|
||||
url.getColonSeparatedKey(), invocation.getMethodName(), secretKey, time);
|
||||
if (parameterEncrypt) {
|
||||
signature = SignatureUtils.sign(invocation.getArguments(), requestString, secretKey);
|
||||
} else {
|
||||
signature = SignatureUtils.sign(requestString, secretKey);
|
||||
return SignatureUtils.sign(invocation.getArguments(), requestString, secretKey);
|
||||
}
|
||||
return signature;
|
||||
return SignatureUtils.sign(requestString, secretKey);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,75 +23,68 @@ import java.io.IOException;
|
|||
import java.io.ObjectOutput;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.security.SignatureException;
|
||||
import java.util.Arrays;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
|
||||
public class SignatureUtils {
|
||||
private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
|
||||
|
||||
public static String sign(String metadata, String key) throws SecurityException {
|
||||
try {
|
||||
return sign(metadata.getBytes(), key);
|
||||
} catch (Exception e) {
|
||||
throw new SecurityException("Failed to generate HMAC : " + e.getMessage(), e);
|
||||
}
|
||||
public static String sign(String metadata, String key) throws RuntimeException {
|
||||
return sign(metadata.getBytes(StandardCharsets.UTF_8), key);
|
||||
}
|
||||
|
||||
public static String sign(Object[] parameters, String metadata, String key) {
|
||||
try {
|
||||
if (parameters == null) {
|
||||
return sign(metadata, key);
|
||||
}
|
||||
boolean notSerializable = Arrays.stream(parameters).anyMatch(parameter -> !(parameter instanceof Serializable));
|
||||
if (notSerializable) {
|
||||
throw new IllegalArgumentException("");
|
||||
}
|
||||
|
||||
Object[] includeMetadata = new Object[parameters.length + 1];
|
||||
System.arraycopy(parameters, 0, includeMetadata, 0, parameters.length);
|
||||
includeMetadata[parameters.length] = metadata;
|
||||
byte[] bytes = toByteArray(includeMetadata);
|
||||
return sign(bytes, key);
|
||||
} catch (Exception e) {
|
||||
throw new SecurityException("Failed to generate HMAC : " + e.getMessage(), e);
|
||||
public static String sign(Object[] parameters, String metadata, String key) throws RuntimeException {
|
||||
if (parameters == null) {
|
||||
return sign(metadata, key);
|
||||
}
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (!(parameters[i] instanceof Serializable)) {
|
||||
throw new IllegalArgumentException("The parameter [" + i + "] to be signed was not serializable.");
|
||||
}
|
||||
}
|
||||
Object[] includeMetadata = new Object[parameters.length + 1];
|
||||
System.arraycopy(parameters, 0, includeMetadata, 0, parameters.length);
|
||||
includeMetadata[parameters.length] = metadata;
|
||||
byte[] includeMetadataBytes;
|
||||
try {
|
||||
includeMetadataBytes = toByteArray(includeMetadata);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to generate HMAC: " + e.getMessage());
|
||||
}
|
||||
return sign(includeMetadataBytes, key);
|
||||
}
|
||||
|
||||
public static String sign(byte[] data, String key) throws SignatureException {
|
||||
String result;
|
||||
private static String sign(byte[] data, String key) throws RuntimeException {
|
||||
Mac mac;
|
||||
try {
|
||||
mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
|
||||
} catch(NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("Failed to generate HMAC: no such algorithm exception " + HMAC_SHA256_ALGORITHM);
|
||||
}
|
||||
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA256_ALGORITHM);
|
||||
try {
|
||||
Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
|
||||
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(),
|
||||
HMAC_SHA256_ALGORITHM);
|
||||
mac.init(signingKey);
|
||||
// compute the hmac on input data bytes
|
||||
byte[] rawHmac = mac.doFinal(data);
|
||||
// base64-encode the hmac
|
||||
result = Base64.getEncoder().encodeToString(rawHmac);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new SignatureException("Failed to generate HMAC : "
|
||||
+ e.getMessage());
|
||||
} catch(InvalidKeyException e) {
|
||||
throw new RuntimeException("Failed to generate HMAC: invalid key exception");
|
||||
}
|
||||
return result;
|
||||
byte[] rawHmac;
|
||||
try{
|
||||
// compute the hmac on input data bytes
|
||||
rawHmac = mac.doFinal(data);
|
||||
} catch (IllegalStateException e) {
|
||||
throw new RuntimeException("Failed to generate HMAC: " + e.getMessage());
|
||||
}
|
||||
// base64-encode the hmac
|
||||
return Base64.getEncoder().encodeToString(rawHmac);
|
||||
}
|
||||
|
||||
static byte[] toByteArray(Object[] parameters) throws Exception {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutput out = null;
|
||||
try {
|
||||
out = new ObjectOutputStream(bos);
|
||||
private static byte[] toByteArray(Object[] parameters) throws IOException {
|
||||
try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)) {
|
||||
out.writeObject(parameters);
|
||||
out.flush();
|
||||
return bos.toByteArray();
|
||||
} finally {
|
||||
try {
|
||||
bos.close();
|
||||
} catch (IOException ex) {
|
||||
// ignore close exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,6 +133,5 @@ class AccessKeyAuthenticatorTest {
|
|||
when(invocation.getArguments()).thenReturn(fakeParams);
|
||||
String signature1 = helper.getSignature(url, invocation, secretKey, String.valueOf(System.currentTimeMillis()));
|
||||
assertNotEquals(signature, signature1);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,43 +16,23 @@
|
|||
*/
|
||||
package org.apache.dubbo.auth.utils;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SignatureUtilsTest {
|
||||
|
||||
|
||||
private Object[] objects = new Object[2];
|
||||
private List<String> list = new ArrayList<>();
|
||||
private String temp = "temp";
|
||||
private String key = "TOKEN";
|
||||
|
||||
{
|
||||
objects[0] = list;
|
||||
objects[1] = temp;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testObjectToByteArray() {
|
||||
|
||||
try {
|
||||
byte[] bytes = SignatureUtils.toByteArray(objects);
|
||||
Assertions.assertNotEquals(0, bytes.length);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
void testEncryptWithObject() {
|
||||
Object[] objects = new Object[] {new ArrayList<>(), "temp"};
|
||||
String encryptWithObject = SignatureUtils.sign(objects, "TestMethod#hello", "TOKEN");
|
||||
Assertions.assertEquals(encryptWithObject, "t6c7PasKguovqSrVRcTQU4wTZt/ybl0jBCUMgAt/zQw=");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testEncryptObject() {
|
||||
String encrypt = SignatureUtils.sign(objects, "TestMethod#hello", key);
|
||||
String encryptNoParams = SignatureUtils.sign(null, "TestMethod#hello", key);
|
||||
Assertions.assertNotNull(encrypt);
|
||||
Assertions.assertNotNull(encryptNoParams);
|
||||
Assertions.assertNotEquals(encrypt, encryptNoParams);
|
||||
void testEncryptWithNoParameters() {
|
||||
String encryptWithNoParams = SignatureUtils.sign(null, "TestMethod#hello", "TOKEN");
|
||||
Assertions.assertEquals(encryptWithNoParams, "2DGkTcyXg4plU24rY8MZkEJwOMRW3o+wUP3HssRc3EE=");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue