从AEM Servlet调用AWS Kendra API时出现签名不匹配错误
问题描述
我在AEM的Servlet中尝试连接AWS Kendra,使用了以下Java代码:
import java.io.IOException; import java.util.List; import javax.servlet.Servlet; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.servlets.SlingAllMethodsServlet; import org.osgi.service.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.kendra.KendraClient; import software.amazon.awssdk.services.kendra.model.AttributeFilter; import software.amazon.awssdk.services.kendra.model.DocumentAttribute; import software.amazon.awssdk.services.kendra.model.DocumentAttributeValue; import software.amazon.awssdk.services.kendra.model.QueryRequest; import software.amazon.awssdk.services.kendra.model.QueryResponse; @Component(service = {Servlet.class}, property = { "sling.servlet.paths=/bin/cookieservlet" } ) public class CookieServlet extends SlingAllMethodsServlet{ Logger log = LoggerFactory.getLogger(CookieServlet.class); protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException{ String accessKey = "AKIAYHKHKJHUMDP4B"; String secretKey = "V9wWb3Hz6oGIUHUKHKDdfyiushdPsOOqzsbdYf/Zxse"; String indexId = "6cc7a433-d9ea-4c68-9b06-76646d6a2529"; AwsCredentials awsCredentials = AwsBasicCredentials.create(accessKey, secretKey); KendraClient kendraClient = KendraClient.builder() .region(Region.US_EAST_1) .credentialsProvider(StaticCredentialsProvider.create(awsCredentials)) .build(); QueryRequest queryRequest = QueryRequest.builder() .queryText(searchWord) .indexId(indexId) .build(); QueryResponse queryResult = kendraClient.query(queryRequest); if(queryRequest!=null){ log.info("Query executed successfully",queryRequest); } response.getWriter().write(queryResult.toString()); response.sendRedirect(targetPageUrl); } }
调用API时收到错误提示:
The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details. (Service: Kendra, Status Code: 400, Request ID: 06ce1fc5-e040-4939-9a85-3e9b245f7a2e)
排查与解决步骤
确认密钥正确性
检查accessKey和secretKey是否完全匹配AWS控制台生成的凭证,避免多余空格、换行或转义字符错误。代码中若存在HTML转义的",需替换为标准双引号,确保密钥为纯文本格式。验证区域一致性
确认Kendra索引所在区域与代码中Region.US_EAST_1配置一致。若索引创建在其他区域(如US_WEST_2),区域不匹配会直接导致签名计算错误。替换硬编码凭证(安全+可靠性提升)
禁止在代码中硬编码AWS凭证,建议采用以下方式:- 通过AEM的OSGi配置存储凭证,在Servlet中注入配置获取密钥
- 若AEM部署在AWS服务(EC2/EKS等)上,使用IAM角色让SDK自动从实例元数据获取凭证,无需手动配置
更新AWS SDK版本
确保使用的AWS SDK for Java v2为最新稳定版,旧版本可能存在签名算法兼容问题。以Maven为例,更新依赖:<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>kendra</artifactId> <version>2.25.0</version> <!-- 使用官方最新版本 --> </dependency>修复未定义变量
代码中searchWord和targetPageUrl变量未定义,虽不直接引发签名错误,但会导致请求异常,需补充变量定义或确保请求参数合法。同步服务器时间
确保运行AEM的服务器时间与AWS服务器时间同步(误差不超过5分钟),AWS签名计算依赖准确时间戳,时间偏差过大也会导致签名不匹配。
内容的提问来源于stack exchange,提问作者Sushma Nalluri

