23、API可视化与微服务安全:OpenAPI与认证授权详解

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
  1. 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);
}
  1. 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         
  1. 启动所需服务:
minikube start     
kubectl apply -f postgresql_kubernetes.yml      
kubectl port-forward service/postgres 5432:5432    
mvn quarkus:dev                                    
mvn clean quarkus:dev -Ddebug=5006    
  1. 手动测试端点:
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>
  1. 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和认证授权机制,我们可以提高开发效率,保障系统的安全性,为用户提供更优质的服务。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值