Quarkus后端调用AWS IoT Core设备影子API时的认证头添加问题
在Quarkus中为AWS IoT Core设备影子API请求添加认证头
AWS IoT Core的设备影子API要求使用SigV4签名进行认证,这是AWS服务的标准HTTP认证方式。下面针对你的Quarkus代码,提供两种可行的实现方案,优先推荐基于Quarkus官方扩展的简化方案。
方案一:使用Quarkus Rest Client AWS扩展(推荐)
Quarkus提供了专门的扩展来自动处理AWS服务的SigV4签名,无需手动实现复杂的签名逻辑。
1. 添加依赖
在你的pom.xml(Maven)或build.gradle(Gradle)中添加扩展依赖:
<!-- Maven --> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-rest-client-aws</artifactId> </dependency>
2. 修改Rest Client接口
修正原接口中查询参数的不规范写法,并添加AWS签名注解:
import io.smallrye.mutiny.Uni; import io.quarkus.rest.client.aws.AwsSign; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; import javax.json.JsonObject; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; @Path("/things/abc") @Produces(MediaType.APPLICATION_JSON) @RegisterRestClient(baseUri = "https://a144gttuytyty10wv7-ats.iot.us-east-1.amazonaws.com") // 添加SigV4签名配置,指定IoT数据服务名和区域 @AwsSign(service = "iotdata", region = "us-east-1") public interface OrganizationProxy { // 用@QueryParam传递影子名称,替代原Path中的硬编码参数 @GET @Path("/shadow") Uni<JsonObject> getOrg(@QueryParam("name") String shadowName); }
3. 更新资源类调用
调整调用逻辑,传入影子名称参数:
import io.smallrye.mutiny.Uni; import org.eclipse.microprofile.rest.client.inject.RestClient; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import javax.json.JsonObject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("/organizations") @ApplicationScoped public class OrganizationResource { @Inject @RestClient OrganizationProxy organizationProxy; @GET @Produces(MediaType.APPLICATION_JSON) public Uni<JsonObject> get() { return organizationProxy.getOrg("shadow-version-1"); } }
4. 配置AWS凭证
Quarkus会自动从以下渠道加载AWS凭证(优先级从高到低):
- 环境变量(
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY) - 系统属性
~/.aws/credentials文件- IAM角色(如果部署在AWS ECS/EKS/EC2等服务上)
本地开发时,可在application.properties中临时配置(生产环境不建议硬编码):
quarkus.aws.region=us-east-1 # 可选:指定凭证类型,默认会自动探测 quarkus.aws.credentials.type=default
方案二:手动实现SigV4签名过滤器
如果无法使用官方扩展,可通过JAX-RS客户端过滤器手动生成SigV4签名头。
1. 添加AWS SDK依赖
<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>auth</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>regions</artifactId> </dependency>
2. 实现签名过滤器
import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.ext.Provider; import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.auth.signer.Aws4Signer; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import java.net.URI; import java.util.HashMap; @Provider public class AwsSigV4Filter implements ClientRequestFilter { private final Aws4Signer signer = Aws4Signer.create(); private final DefaultCredentialsProvider credentialsProvider = DefaultCredentialsProvider.create(); private final Region region = Region.US_EAST_1; private final String serviceName = "iotdata"; @Override public void filter(ClientRequestContext requestContext) { URI uri = requestContext.getUri(); // 构建AWS签名所需的请求对象 SdkHttpFullRequest.Builder requestBuilder = SdkHttpFullRequest.builder() .method(SdkHttpMethod.fromValue(requestContext.getMethod())) .uri(uri) .headers(new HashMap<>(requestContext.getHeaders())); // 生成签名 SdkHttpFullRequest signedRequest = signer.sign( requestBuilder.build(), credentialsProvider.resolveCredentials(), serviceName, region ); // 替换请求头为签名后的头 requestContext.getHeaders().clear(); signedRequest.headers().forEach((key, values) -> requestContext.getHeaders().put(key, values)); } }
3. 注册过滤器到Rest Client
在OrganizationProxy接口上添加过滤器注册:
@RegisterRestClient(baseUri = "https://a144gttuytyty10wv7-ats.iot.us-east-1.amazonaws.com") @RegisterProvider(AwsSigV4Filter.class) // 注册签名过滤器 public interface OrganizationProxy { // 接口方法同方案一 }
内容的提问来源于stack exchange,提问作者Vinura Jayalath
相关产品推荐
相关产品推荐

