blob: 1ba1b17b799e705118d80561c39591e159d4282b [file] [log] [blame]
/*
* 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.apache.dubbo.auth;
import org.apache.dubbo.auth.exception.AccessKeyNotFoundException;
import org.apache.dubbo.auth.exception.RpcAuthenticationException;
import org.apache.dubbo.auth.model.AccessKeyPair;
import org.apache.dubbo.auth.spi.AccessKeyStorage;
import org.apache.dubbo.auth.spi.Authenticator;
import org.apache.dubbo.auth.utils.SignatureUtils;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.Invocation;
public class AccessKeyAuthenticator implements Authenticator {
@Override
public void sign(Invocation invocation, URL url) {
String currentTime = String.valueOf(System.currentTimeMillis());
String consumer = url.getParameter(CommonConstants.APPLICATION_KEY);
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);
}
@Override
public void authenticate(Invocation invocation, URL url) throws RpcAuthenticationException {
String accessKeyId = String.valueOf(invocation.getAttachment(Constants.AK_KEY));
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");
}
AccessKeyPair accessKeyPair = null;
try {
accessKeyPair = getAccessKeyPair(invocation, url);
} catch (Exception e) {
throw new RpcAuthenticationException("Failed to authenticate , can't load the accessKeyPair", e);
}
String computeSignature = getSignature(url, invocation, accessKeyPair.getSecretKey(), requestTimestamp);
boolean success = computeSignature.equals(originSignature);
if (!success) {
throw new RpcAuthenticationException("Failed to authenticate, signature is not correct");
}
}
AccessKeyPair getAccessKeyPair(Invocation invocation, URL url) {
AccessKeyStorage accessKeyStorage = ExtensionLoader.getExtensionLoader(AccessKeyStorage.class)
.getExtension(url.getParameter(Constants.ACCESS_KEY_STORAGE_KEY, Constants.DEFAULT_ACCESS_KEY_STORAGE));
AccessKeyPair accessKeyPair = null;
try {
accessKeyPair = accessKeyStorage.getAccessKey(url, invocation);
if (accessKeyPair == null || StringUtils.isEmpty(accessKeyPair.getAccessKey()) || StringUtils.isEmpty(accessKeyPair.getSecretKey())) {
throw new AccessKeyNotFoundException("AccessKeyId or secretAccessKey not found");
}
} catch (Exception e) {
throw new RuntimeException("Can't load the AccessKeyPair from accessKeyStorage", e);
}
return accessKeyPair;
}
String getSignature(URL url, Invocation invocation, String secretKey, String 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 signature;
}
}