API可视化与微服务安全:OpenAPI与认证授权详解
1. OpenAPI内容过滤
MicroProfile OpenAPI规范提供了在返回生成的OpenAPI文档之前对其进行自定义的方法。开发者可以通过实现
OASFilter
接口来进行定制。以下是一个示例代码:
public class OpenApiFilter implements OASFilter {
@Override
public Operation filterOperation(Operation operation) {
if (operation.getOperationId().equals("closeAccount")) {
operation.setTags(List.of("close-account"));
}
return operation;
}
}
编写好过滤器后,需要在
application.properties
中进行配置以激活它,添加如下配置:
mp.openapi.filter=quarkus.accounts.OpenApiFilter
刷新Swagger UI页面,就能看到过滤器创建的新方法分组。
2. 设计优先开发
设计优先开发,也称为契约优先开发,是指在编写任何代码之前,通过描述正在开发的服务来创建OpenAPI文档。这种方法可以在编写代码之前验证API是否合理。一旦验证通过,就可以使用OpenAPI生成器根据OpenAPI文档生成服务,作为实现服务的起点。
需要注意的是,代码生成是单向过程。当从OpenAPI文档生成服务方法后,一旦实现了这些方法,若不丢失实现内容,就无法重新生成方法签名。因此,开发者需要确保在OpenAPI文档不再预期更改后再生成服务方法。如果文档发生更改,则需要手动同步服务实现和OpenAPI文档。
有许多无需代码即可使用OpenAPI规范设计API的工具,例如Swagger Editor(https://swagger.io/tools/swagger-editor/)和Apicurio Studio(https://www.apicur.io/studio/)等。
3. 使用现有OpenAPI文档
为了展示如何在Quarkus服务中使用现有的OpenAPI文档,我们将之前的Account服务复制到
/chapter12/account-service-external-openapi
。主要区别在于,从
AccountResource
和
Account
类中移除了所有对MicroProfile OpenAPI注解的引用,OpenAPI定义将来自外部文件,同时移除了
application.properties
中的配置和
OpenApiFilter
。
具体操作步骤如下:
1. 下载Account服务的YAML文件,从
http://localhost:8080/q/openapi
下载,将下载的文件从
openapi
重命名为
openapi.yaml
,然后将其移动到新项目的
/src/main/resources/META-INF
目录中。
2. 在
application.properties
中添加
mp.openapi.scan.disable=true
,以确保项目中的静态OpenAPI文档按原样提供。
3. 使用
mvn quarkus:dev
启动服务,并验证OpenAPI文档和Swagger UI的外观和行为是否符合预期。
4. 结合文件和注解
我们可以将静态文件与代码中的注解结合使用。有以下两种方式:
- OpenAPI文档作为主要依据,对代码中的注解进行小修改。
- OpenAPI文档包含通用模式定义,代码注解引用这些定义。
操作步骤如下:
1. 从
application.properties
中移除
mp.openapi.scan.disable
配置,使代码中的注解能够与静态OpenAPI文档混合。
2. 在
AccountResource.allAccounts()
方法中添加
@Tag(name = "all-accounts", description = "Separate grouping because we can")
,查看Swagger UI的调整情况。
5. 代码优先还是OpenAPI优先
在将OpenAPI文档与代码集成时,有代码优先和OpenAPI优先两种方式。
-
代码优先
:需要在代码中添加
@APIResponse
、
@RequestBody
、
@Parameter
、
@Operation
、
@Tag
等注解,以自定义生成的OpenAPI文档内容。
-
OpenAPI优先
:定义一个代表所需服务的OpenAPI文档,并引用静态文件来提供该文档。
以下是两种方式适用的场景:
| 方式 | 适用场景 |
| ---- | ---- |
| OpenAPI优先 | 非开发者定义API,更可能使用OpenAPI工具创建;多个团队协作,在开发前使用共享API定义可避免后续问题。 |
| 代码优先 | 服务已实现,自动生成OpenAPI文档并按需添加注解更方便;API的具体结构和内容未知,需要进行原型设计时。 |
此外,使用代码注解时还需要考虑对代码本身的影响,例如添加注解后的代码可能会变得更大且可读性降低。
6. 认证和授权概述
在企业应用中,为防止信息被未经授权的访问,需要对应用进行安全保护。主要的安全措施包括认证和授权:
-
认证
:用户通过提供用户名和密码或经过验证的JWT令牌等凭证,验证自己的身份。认证后的用户可以被分配角色,如银行客户和银行柜员。
-
授权
:授予对资源的访问权限。只有被分配到适当角色的认证用户才能访问安全端点。
-
身份提供者
:管理用户身份的设施,如LDAP、文件、数据库或Keycloak。
-
安全上下文
:应用程序为每个请求包含一个安全上下文,其中包括认证用户分配的角色。
以下是Quarkus支持的认证和授权机制:
| 认证机制 | 描述 |
| ---- | ---- |
| Basic
| HTTP用户代理(如Web浏览器)请求用户凭证。 |
| Form | 呈现Web表单(如HTML)以获取用户凭证。 |
| Mutual TLS | 根据用户的X.509证书进行认证。 |
| OpenID Connect (OIDC)
| 基于OAuth 2.0的行业标准认证层,将认证委托给OpenID Connect提供者(如Keycloak),Quarkus支持OIDC授权码和隐式流。 |
| MicroProfile JWT* | 支持包含已验证用户身份的JSON Web Token(JWT)承载令牌。 |
| LDAP | LDAP服务器请求用户凭证。 |
| 授权机制 | 描述 |
|---|---|
| OAuth 2.0 | 用于授予第三方访问用户受保护资源的行业标准协议。 |
| Configuration* | 使用配置属性指定应用程序授权规则。 |
| Annotations* |
使用Jakarta Annotations规范中的安全相关注解(如
@PermitAll
和
@RolesAllowed
)指定应用程序授权规则。
|
7. 使用基于文件的认证和授权
可以使用Quarkus内置的HTTP策略配置和基于文件的身份提供者来保护Transaction服务。具体操作步骤如下:
1. 添加
quarkus-elytron-security-properties-file
扩展:
cd transaction-service
mvn quarkus:add-extension -Dextensions=quarkus-elytron-security-properties-file
-
在
TransactionResource.java中创建一个受文件安全保护的方法:
@GET
@Path("/config-secure/{acctnumber}/balance")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response secureConfigGetBalance(@PathParam("acctnumber") Long
accountNumber) {
return getBalance(accountNumber);
}
-
在
Transaction服务的application.properties中添加配置属性:
# Security using Quarkus built-in policy controls
quarkus.http.auth.permission.customer.paths=/transactions/config-secure/*
quarkus.http.auth.permission.customer.methods=GET
quarkus.http.auth.permission.customer.policy=authenticated
# Security - Embedded users/roles (File realm)
%dev.quarkus.security.users.embedded.enabled=true
%dev.quarkus.security.users.embedded.plain-text=true
%dev.quarkus.security.users.embedded.users.duke=duke
%dev.quarkus.security.users.embedded.roles.duke=customer
%dev.quarkus.security.users.embedded.users.quarkus=quarkus
%dev.quarkus.security.users.embedded.roles.quarkus=teller
# Enable HTTP basic authentication, which this application uses
# only during development
%dev.quarkus.http.auth.basic=true
- 启动所需服务:
minikube start
kubectl apply -f postgresql_kubernetes.yml
kubectl port-forward service/postgres 5432:5432
mvn quarkus:dev
mvn clean quarkus:dev -Ddebug=5006
- 手动测试端点:
TRANSACTION_URL=http://localhost:8088
curl -i \
-H "Accept: application/json" \
$TRANSACTION_URL/transactions/config-secure/444666/balance
如果未提供认证用户,将返回
HTTP/1.1 401 Unauthorized
。使用认证用户进行测试:
curl -i \
-H "Accept: application/json" \
--user duke:duke \
$TRANSACTION_URL/transactions/config-secure/444666/balance
如果用户认证成功,将返回
HTTP/1.1 200 OK
和账户余额。
8. 限制特定角色的访问
为了限制特定角色的访问,可以将认证授权策略替换为以下配置:
quarkus.http.auth.policy.customer-policy.roles-allowed=customer
quarkus.http.auth.permission.customer.paths=/transactions/config-secure/*
quarkus.http.auth.permission.customer.methods=GET
quarkus.http.auth.permission.customer.policy=customer-policy
# quarkus.http.auth.permission.customer.policy=authenticated
使用
curl
手动测试
customer-policy
:
curl -i \
-H "Accept: application/json" \
--user quarkus:quarkus \
$TRANSACTION_URL/transactions/config-secure/444666/balance
curl -i \
-H "Accept: application/json" \
--user duke:duke \
$TRANSACTION_URL/transactions/config-secure/444666/balance
如果用户
quarkus
(柜员角色)访问,将返回
HTTP/1.1 403 Forbidden
;如果用户
duke
(客户角色)访问,将返回
HTTP/1.1 200 OK
和账户余额。
9. 测试安全端点
Quarkus支持通过
@TestSecurity
注解定义用户和角色来测试安全端点。操作步骤如下:
1. 在
Transaction
服务的
pom.xml
中添加
quarkus-test-security
依赖:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<scope>test</scope>
</dependency>
-
在
transaction-service/test/java/io/quarkus/transactions目录下创建SecurityTest.java文件:
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.QuarkusTestResource;
import io.quarkus.test.security.TestSecurity;
import org.junit.jupiter.api.Test;
@QuarkusTest
@QuarkusTestResource(WiremockAccountService.class)
@TestSecurity(user = "duke", roles = { "customer" })
public class SecurityTest {
@Test
public void built_in_security() {
given()
.when()
.get("/transactions/config-secure/{acctNumber}/balance", 121212)
.then()
.statusCode(200)
.body(containsString("435.76"));
}
}
综上所述,通过OpenAPI可以有效地对API进行可视化和管理,而认证和授权机制则能确保微服务的安全性。开发者可以根据具体需求选择合适的开发方式和安全策略。
API可视化与微服务安全:OpenAPI与认证授权详解
10. 安全机制总结与流程梳理
在前面的内容中,我们详细介绍了多种认证和授权机制,下面通过一个流程图来梳理整个安全访问的流程:
graph LR
A[用户发起请求] --> B{请求是否需要认证?}
B -- 是 --> C{使用何种认证方式?}
C -- Basic --> D[输入用户名和密码]
C -- OpenID Connect --> E[重定向到OIDC提供者]
C -- MicroProfile JWT --> F[提供JWT令牌]
D --> G{认证是否成功?}
E --> G
F --> G
G -- 是 --> H{请求是否需要授权?}
H -- 是 --> I{使用何种授权方式?}
I -- Configuration --> J[检查配置属性]
I -- Annotations --> K[检查代码注解]
J --> L{授权是否通过?}
K --> L
L -- 是 --> M[访问资源]
B -- 否 --> M
G -- 否 --> N[返回401 Unauthorized]
L -- 否 --> O[返回403 Forbidden]
从这个流程图可以清晰地看到,用户请求首先会判断是否需要认证,如果需要则选择相应的认证方式进行认证。认证成功后,再判断是否需要授权,根据不同的授权方式进行检查,最终决定是否允许用户访问资源。
11. 不同开发方式的对比与选择
在前面我们提到了代码优先和OpenAPI优先两种开发方式,下面通过一个表格来更直观地对比它们的优缺点:
| 开发方式 | 优点 | 缺点 | 适用场景 |
| ---- | ---- | ---- | ---- |
| 代码优先 | 服务已实现时,自动生成OpenAPI文档方便快捷;便于根据实际开发情况灵活调整API内容 | 代码中添加大量注解会增加代码量,降低可读性 | 服务已存在,需要快速生成文档;API结构和内容需要在开发过程中逐步确定 |
| OpenAPI优先 | 非开发者也能参与API设计;团队协作时可提前确定API规范,避免后续问题 | 代码生成是单向过程,修改OpenAPI文档后可能需要手动同步代码 | 非开发者主导API设计;多个团队协作开发,需要统一API标准 |
开发者在选择开发方式时,需要综合考虑项目的实际情况,如团队成员构成、项目进度、API的稳定性等因素。
12. 安全测试的重要性与扩展
在前面我们介绍了使用
@TestSecurity
注解进行安全测试的方法,安全测试对于保障微服务的安全性至关重要。除了测试特定角色的访问权限外,还可以进行以下扩展测试:
-
边界测试
:测试不同边界条件下的安全访问,例如使用无效的用户名、密码或JWT令牌。
-
并发测试
:模拟多个用户同时发起请求,测试系统在高并发情况下的安全性能。
-
异常测试
:测试系统在遇到异常情况时的安全处理,例如认证服务器故障、授权配置错误等。
以下是一个边界测试的示例代码,在
SecurityTest.java
中添加一个新的测试方法:
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.QuarkusTestResource;
import io.quarkus.test.security.TestSecurity;
import org.junit.jupiter.api.Test;
@QuarkusTest
@QuarkusTestResource(WiremockAccountService.class)
@TestSecurity(user = "duke", roles = { "customer" })
public class SecurityTest {
@Test
public void built_in_security() {
given()
.when()
.get("/transactions/config-secure/{acctNumber}/balance", 121212)
.then()
.statusCode(200)
.body(containsString("435.76"));
}
@Test
public void test_invalid_user() {
given()
.when()
.get("/transactions/config-secure/{acctNumber}/balance", 121212)
.auth().basic("invalidUser", "invalidPassword")
.then()
.statusCode(401);
}
}
13. 综合应用与最佳实践
在实际项目中,我们可以将前面介绍的各种技术综合应用,形成一套最佳实践:
1.
设计阶段
:如果有非开发者参与或者多个团队协作,采用OpenAPI优先的方式,使用工具如Swagger Editor或Apicurio Studio设计API文档,确保各方对API的理解一致。
2.
开发阶段
:根据OpenAPI文档生成代码框架,在开发过程中根据实际情况使用代码优先的方式,添加必要的注解对OpenAPI文档进行微调。
3.
安全配置阶段
:根据项目的安全需求,选择合适的认证和授权机制。在开发和测试阶段,可以使用基于文件的认证和授权方式,方便快捷;在生产环境中,建议使用更安全的机制,如OpenID Connect或MicroProfile JWT。
4.
测试阶段
:使用
@TestSecurity
注解等工具进行全面的安全测试,包括正常情况和异常情况的测试,确保系统的安全性。
通过遵循这些最佳实践,我们可以提高开发效率,保证API的质量和系统的安全性。
14. 未来发展趋势与展望
随着微服务架构的不断发展,API可视化和安全机制也会不断演进。未来可能会出现以下趋势:
-
更强大的API设计工具
:工具将更加智能化,能够自动生成更完善的API文档,支持更多的格式和标准。
-
更安全的认证和授权机制
:随着区块链、量子加密等技术的发展,可能会出现更安全、更高效的认证和授权方式。
-
自动化的安全测试
:测试工具将更加自动化,能够在开发过程中实时检测安全漏洞,提高系统的安全性。
开发者需要不断关注这些趋势,及时学习和应用新的技术,以适应不断变化的开发需求。
总之,API可视化和微服务安全是现代软件开发中不可或缺的部分。通过合理运用OpenAPI和认证授权机制,我们可以提高开发效率,保障系统的安全性,为用户提供更优质的服务。
超级会员免费看
841

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



