微服务安全:JWT与MicroProfile JWT的应用
1. JWT签名验证
JWT(Json Web Tokens)是一种用于在网络应用中安全传输信息的开放标准。每个JWT都会使用头部 alg 声明中定义的算法进行签名,以确保其未被篡改。验证JWT签名的一种简单方法是将原始令牌内容粘贴到 https://jwt.io/#encoded-jwt 提供的表单中。具体步骤如下:
1. 将JWT粘贴到编码表单中,此时JWT的头部和有效负载部分将显示声明值。
2. JWT头部:头部声明(尽管值不一定相同)将与特定声明匹配。
3. JWT有效负载:声明(同样值不一定相同)将与另一些特定声明匹配。
4. 由于未提供公钥,签名无法验证。
若要获取公钥,可运行如下命令,输出结果应类似于以下示例:
scripts/createpem.sh
以下是获取到的公钥示例:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjJ/GYpCkgfYT1HYpa96AP8djbKiv25Yh
VlZcHcIt2QX4VZPJM/qntF2m7ubPSz3zHHNQUOWYl+3xIo4EFfCcTPTBgL0aSlCsuT5+0RuajsFj
ejLGa19p3eKuBjtB0buqI4SbxpitvZj4L4beBdFj+r2NZZNxeFFMrd9lORW3b4cUmk8tS6ZrgbTK
Ij3adjlVMYHOkGQNNGBf1KJkdbi8UQtXaATuyFHiQCCYY/ENWGGomu+dXqvqnRRsdWBndsUcCNe+
NPwT1z3lbfYoXkldWFVvXjBnNme/f8mCMWuKBz4fGZUkt7Sdc5FPnFpsbT+0inarxIov3puDxHbB
gNJ9xwIDAQAB
-----END PUBLIC KEY-----
将此公钥粘贴到 jwt.io 表单的公钥字段中,即可完成签名验证。需要注意的是,不同安装环境下的令牌和公钥是不同的,使用示例中的公钥验证其他安装环境下的令牌会失败。
2. JWT有效负载声明
JWT的有效负载包含了一系列声明,以下是一些MicroProfile JWT所需的重要声明:
| 声明 | 描述 |
| ---- | ---- |
| typ | 声明令牌的媒体类型 |
| iss* | MicroProfile JWT的颁发者 |
| sub* | 标识JWT的主体 |
| exp* | JWT的过期时间(自1970年1月1日起的秒数) |
| iat* | JWT的颁发时间(自1970年1月1日起的秒数) |
| jti* | JWT的唯一标识符,可用于防止JWT被重放 |
| upn* | 一个人类可读的MicroProfile JWT自定义声明,用于唯一标识令牌的主体或用户主体。若该声明缺失,MicroProfile JWT将回退到 preferred_username 声明;若 preferred_username 也缺失,则使用 sub 声明 |
| groups* | MicroProfile JWT自定义声明,列出主体所属的组 |
3. 使用MicroProfile JWT保护交易服务
在对JWT和MicroProfile JWT API有了深入理解后,我们可以使用MicroProfile JWT来保护交易服务。具体步骤如下:
1. 添加扩展 :在编写代码之前,需要添加 quarkus-smallrye-jwt 扩展。
cd transaction_service
mvn quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-jwt"
# 如果交易服务未运行,启动它
mvn clean quarkus:dev -Ddebug=5006
- 更新配置文件 :在
application.properties中更新公钥配置。
# 配置MicroProfile JWT
mp.jwt.verify.publickey=<INSERT PUBLIC KEY HERE>
mp.jwt.verify.issuer=http://keycloak.local/auth/realms/bank
- 添加安全REST方法端点 :在
TransactionResource.java中添加一个方法,用于测试JWT是否允许访问该方法。
@GET
@RolesAllowed("customer")
@Path("/jwt-secure/{acctnumber}/balance")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response jwtGetBalance(
@PathParam("acctnumber") Long accountNumber) {
return getBalance(accountNumber);
}
- 验证访问 :通过以下命令验证端点的访问。
# 在新终端窗口启动账户服务(如果未运行)
cd account-service
mvn quarkus:dev
# 在章节顶级目录的新窗口中重启交易服务
cd transaction-service
mvn clean quarkus:dev -Ddebug=5006
# 在章节顶级目录的新窗口中获取令牌
TOKEN=`scripts/gettoken.sh`
TRANSACTION_URL=http://localhost:8088
curl -i \
-H "Accept: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
$TRANSACTION_URL/transactions/jwt-secure/444666/balance
如果访问端点时未提供有效的承载令牌或使用了过期令牌,将收到 HTTP/1.1 401 Unauthorized 消息。
4. 传播JWT
请求可能会跨越多个受保护的微服务,使用JWT可以使安全上下文随请求一起传递,从而实现对这些受保护微服务的访问。接下来,我们将介绍如何将JWT从交易服务传播到账户服务。
4.1 保护账户服务端点
保护账户服务端点的过程与保护交易服务端点类似,具体步骤如下:
1. 添加扩展 :
cd account_service
mvn quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-jwt"
- 更新配置文件 :
# 配置MicroProfile JWT
mp.jwt.verify.publickey=<INSERT PUBLIC KEY HERE>
mp.jwt.verify.issuer=http://keycloak.local/auth/realms/bank
- 添加安全方法 :在
AccountResource.java中添加一个安全方法,用于获取银行余额。
@RolesAllowed("customer")
@GET
@Path("/jwt-secure/{acctNumber}/balance")
public BigDecimal getBalanceJWT(
@PathParam("acctNumber") Long accountNumber) {
return getBalance(accountNumber);
}
4.2 从交易服务传播JWT到账户服务
交易服务使用MicroProfile REST客户端(通过 AccountService.java )访问账户服务。我们需要在 AccountService.java 中添加一个新方法,用于调用账户服务的新安全端点。
@GET
@Path("/jwt-secure/{acctNumber}/balance")
BigDecimal getBalanceSecure(@PathParam("acctNumber") Long accountNumber);
同时,更新 TransactionResource.jwtGetBalance() 方法,以调用新的安全端点。
@GET
@RolesAllowed("customer")
@Path("/jwt-secure/{acctnumber}/balance")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response jwtGetBalance(
@PathParam("acctnumber") Long accountNumber) {
String balance =
accountService.getBalanceSecure(accountNumber).toString();
return Response.ok(balance).build();
}
最后,为了使交易服务能够安全地访问账户服务,需要在交易服务的 application.properties 中更新配置,以传递 Authorization 头部。
org.eclipse.microprofile.rest.client.propagateHeaders=Special-Header,Authorization
5. 在Kubernetes中运行服务
将服务部署到Kubernetes的步骤如下:
cd account-service
eval $(minikube -p minikube docker-env)
mvn clean package -DskipTests -Dquarkus.kubernetes.deploy=true
cd ../transaction-service
mvn clean package -DskipTests -Dquarkus.kubernetes.deploy=true
export TRANSACTION_URL=`minikube service transaction-service --url`
export TOKEN=`../scripts/gettoken.sh`
curl -i \
-H "Accept: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
$TRANSACTION_URL/transactions/jwt-secure/444666/balance
需要注意的是,在Quarkus 2.x中,如果尝试重新部署已经存在于Kubernetes中的应用程序,使用 mvn package -Dquarkus.kubernetes.deploy=true 会导致错误。可以通过先使用 kubectl delete -f /target/kubernetes/minikube.yaml 删除应用程序来解决这个问题。
6. 总结
- 身份验证和授权是Web应用程序必要的安全策略。
- Quarkus支持多种身份验证和授权机制。
- 在
application.properties中定义用户和授权策略是一种高效的开发方法。 - Quarkus提供了一些实用功能,可简化对受保护应用程序的测试。
- OIDC代码授权流程通常使用Web表单获取用户身份并返回JWT。
- JWT可以使用OIDC隐式流程在服务之间传播用户身份。
- Quarkus通过WireMock OIDC授权服务器增强了OIDC测试体验。
通过以上步骤,我们可以实现使用JWT和MicroProfile JWT来保护微服务,并在Kubernetes中运行这些服务,从而提高系统的安全性和可扩展性。
graph LR
A[交易服务] -->|获取令牌| B[Keycloak]
A -->|携带JWT请求| C[账户服务]
C -->|验证JWT| D[返回结果]
graph LR
A[开始] --> B[添加扩展]
B --> C[更新配置文件]
C --> D[添加安全方法]
D --> E[验证访问]
E --> F[传播JWT]
F --> G[部署到Kubernetes]
G --> H[结束]
微服务安全:JWT与MicroProfile JWT的应用
7. 相关技术点索引
以下是一些在微服务安全中涉及的重要技术点及其相关信息:
| 技术点 | 相关描述 |
| ---- | ---- |
| @APIResponse | 用于定义API响应信息 |
| @Asynchronous | 可使方法在单独线程中执行 |
| @Bulkhead | 用于限制并发 |
| @CircuitBreaker | 避免重复失败,有相关参数和异常处理 |
| @ClientHeaderParam | 用于设置客户端请求头参数 |
| @ConfigMapping | 用于配置映射 |
| @ConfigProperties | 用于分组配置属性 |
| @ConfigProperty | 用于获取配置属性 |
| @Fallback | 提供失败时的回退处理 |
| @HeaderParam | 用于获取请求头参数 |
| @Inject | 用于依赖注入 |
| @Liveness | 用于定义存活检查 |
| @Readiness | 用于定义就绪检查 |
| @Retry | 用于从临时失败中恢复 |
| @Timeout | 用于设置执行超时 |
| @Traced | 用于跟踪操作 |
8. 微服务配置相关
配置微服务是确保其正常运行和安全的重要环节,以下是一些关键的配置方面:
- 配置源 :微服务的配置可以来自多种源,如环境变量、配置文件等。
- 分组配置属性 :使用 @ConfigProperties 可以将相关的配置属性进行分组,方便管理。例如:
@ConfigProperties(prefix = "bank")
public class BankConfig {
private String name;
private boolean mobileBanking;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isMobileBanking() {
return mobileBanking;
}
public void setMobileBanking(boolean mobileBanking) {
this.mobileBanking = mobileBanking;
}
}
- 配置文件 :在
application.properties中可以进行各种配置,如公钥验证、颁发者验证等。
# 配置MicroProfile JWT
mp.jwt.verify.publickey=<INSERT PUBLIC KEY HERE>
mp.jwt.verify.issuer=http://keycloak.local/auth/realms/bank
9. 微服务健康检查
微服务的健康检查对于确保系统的稳定性至关重要,以下是一些相关信息:
- MicroProfile Health规范 :定义了微服务的存活和就绪检查机制。
- 存活检查 :用于检查服务是否正在运行。例如,账户服务的存活检查可以通过以下代码实现:
@Liveness
public class AccountHealthReadinessCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
// 检查逻辑
if (isAccountServiceAlive()) {
return HealthCheckResponse.up("Account service is alive");
} else {
return HealthCheckResponse.down("Account service is down");
}
}
private boolean isAccountServiceAlive() {
// 具体检查逻辑
return true;
}
}
- **就绪检查**:用于检查服务是否准备好接收请求。
- Kubernetes探针 :Kubernetes可以使用存活和就绪探针来监控微服务的状态。可以在部署文件中配置探针,例如:
apiVersion: v1
kind: Pod
metadata:
name: account-service
spec:
containers:
- name: account-service
image: account-service:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /q/health/live
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /q/health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
10. 微服务监控与追踪
微服务的监控和追踪可以帮助我们了解系统的运行状态和性能,以下是一些相关技术:
- MicroProfile Metrics :用于收集微服务的指标,如计数器、计时器等。可以通过注解来定义指标,例如:
import org.eclipse.microprofile.metrics.annotation.Counted;
@Counted(name = "balance_requests", description = "Number of balance requests")
public Response jwtGetBalance(
@PathParam("acctnumber") Long accountNumber) {
return getBalance(accountNumber);
}
- Jaeger :用于分布式追踪,可以帮助我们了解请求在微服务之间的调用路径。安装和配置Jaeger的步骤如下:
- 在Minikube环境中设置相关环境变量。
- 安装Jaeger Operator。
- 配置追踪采样策略。
- 在微服务中集成Jaeger客户端。
graph LR
A[微服务配置] --> B[配置源]
A --> C[分组配置属性]
A --> D[配置文件]
E[微服务健康检查] --> F[MicroProfile Health规范]
E --> G[Kubernetes探针]
H[微服务监控与追踪] --> I[MicroProfile Metrics]
H --> J[Jaeger]
11. 总结与展望
通过使用JWT和MicroProfile JWT,我们可以有效地保护微服务的安全,实现身份验证和授权。同时,结合Kubernetes的部署和管理,以及相关的监控和追踪技术,可以提高系统的稳定性和可维护性。
在未来的微服务开发中,我们可以进一步探索以下方面:
- 优化JWT的使用,如减少令牌大小、提高验证效率等。
- 结合更多的安全机制,如多因素身份验证、加密传输等。
- 深入研究微服务的性能优化和故障处理,以应对更复杂的业务场景。
graph LR
A[当前实现] --> B[优化JWT使用]
A --> C[结合更多安全机制]
A --> D[深入研究性能优化和故障处理]
B --> E[未来发展]
C --> E
D --> E
通过不断地学习和实践,我们可以更好地掌握微服务安全的技术,为构建更安全、高效的系统奠定基础。
微服务安全:JWT与MicroProfile JWT应用
超级会员免费看
85

被折叠的 条评论
为什么被折叠?



