当前位置: 首页 > news >正文

通过 Keycloak 结合 OAuth2.0协议进行 Amazon API Gateway 鉴权

1. 简介

本文介绍了如何通过 Keycloak,并结合 Amazon API Gateway 内置的授权功能,完成对 Amazon 资源请求的鉴权过程。API Gateway 帮助开发者安全的的创建、发布、维护并管理 API 的访问。在中国区,由于Cognito 仍未上线,因此使用 Keycloak 作为 API 调用的鉴权服务,具有重要的实际意义。

亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界最前沿技术,观点,和项目,并将中国优秀开发者或技术推荐给全球云社区。如果你还没有关注/收藏,看到这里请一定不要匆匆划过,点这里让它成为你的技术宝库!

本文共分为四大模块:

简介:对 Keycloak、OAuth2.0以及 Amazon API Gateway Authorizer 进行了介绍;

配置说明:对环境的设定进行了详细的说明,包括 DynamoDB 的设定以及 Keycloak 环境的搭建和设置;

验证 JWT Authorizer:通过 Postman 对 API Gateway 的授权功能进行验证;

总结:对全文的总结。

1.1 关于 Keycloak

Keycloak 是一个开源并广泛应用于用户身份管理与授权的解决方案。Keycloak 支持多种协议和标准,包括 OpenID Connect,OAuth2.0和SAML2.0。同时 Keycloak 可以集成与已有的 LDAP 或者 Active Directory 服务集成,用于单点登录。基于 OAuth2.0,Keycloak 还可以通过 JWT Token 完成对 API 的鉴权,本文基于此场景,结合 Keycloak 通过 Amazon Gateway 的 Authorizer 完成请求的鉴权。

1.2 关于OAuth2.0

OAuth2.0全称为 Open Authorization 2.0,为用于鉴权的协议。通过 OAuth 协议,可以授权第三方应用请求用户的资源,而不需要资源的拥有者直接向第三方提供任何验证凭据信息。 OAuth2.0 鉴权流程

image.png

1.3 关于 Amazon API Gateway Authorizer

在本文中,我们以 HTTP API 为例,利用 HTTP API 已内置的授权功能进行 API 请求的鉴权。如果使用 REST API,则需要通过结合 Lambda 进行 JWT Token 的校验,可参照此说明文档进行配置。

2. 配置说明

image.png

在本设计中,用户通过调用 API Gateway 中定义好的 API ,访问 Amazon 上的数据库资源。我们通过定义2个路由,并集成 Lambda 函数,完成对 DynamoDB 数据的读/写。

  • GET /items:不需要进行鉴权,可以直接通过 API Gateway 获取DynamoDB 数据。
  • POST /items:需要进行鉴权,通过 API Gateway 校验请求 Token,验证成功后,向 DynamoDB 写入数据。
2.2 预置条件
  • 创建一个 DynamoDB Table,DemoTable。
  • 在 Amazon API Gateway 创建 HTTP API,并与 Lambda 进行集成。

DynomoDB 设置

image.png

  • 分区键:pk
  • 排序键:sk
  • 其他保留默认配置

API Gateway 设置

创建 API Gateway,为 API Gateway 创建2条路由,并关联 Lambd 函数,列表如下:

image.png

Lambda 函数样例

  • GetItemsLambda
import boto3
import os
import json
import botocoredef lambda_handler(event, context):try:client = boto3.resource("dynamodb")table_name = os.environ.get('DDB_TABLE')table = client.Table(table_name)scanning_result = table.scan()return {'statusCode': 200,'body': json.dumps(scanning_result),'headers': {'Content-Type': 'application/json'},'isBase64Encoded': 'false'}except botocore.exceptions.ClientError as e:print(e)

  • GetItemsLambdaRole Policy:
"Version": "2012-10-17","Statement": [{"Action": ["xray:PutTraceSegments","xray:PutTelemetryRecords"],"Resource": "*","Effect": "Allow"},{"Action": ["dynamodb:DescribeTable","dynamodb:Query","dynamodb:Scan"],"Resource": ["arn:aws:dynamodb:us-east-1:123456789012:table/DemoTable"],"Effect": "Allow"}]
}

  • CreateItemsLambda:
import json
import datetime
import boto3
import os
import botocore
import uuiddef lambda_handler(event, context):try:client = boto3.client('dynamodb')table_name = os.environ.get('DDB_TABLE')req_body = json.loads(event["body"])req_user = event["requestContext"]["authorizer"]["jwt"]["claims"]["email"]ct = datetime.datetime.now()client.put_item(TableName = table_name,Item = {'pk': {'S':req_user},'sk': {'S':'item#' + str(uuid.uuid4())},'title': {'S':req_body["title"]},'timeCreated': {'S': ct.isoformat()}})return {'statusCode': 200,'body': json.dumps('New Item Created')}except botocore.exceptions.ClientError as e:print(e)

  • CreateItemsLambdaRole Policy:
{"Version": "2012-10-17","Statement": [{"Action": ["xray:PutTraceSegments","xray:PutTelemetryRecords"],"Resource": "*","Effect": "Allow"},{"Action": ["dynamodb:BatchGetItem","dynamodb:GetRecords","dynamodb:GetShardIterator","dynamodb:Query","dynamodb:GetItem","dynamodb:Scan","dynamodb:ConditionCheckItem","dynamodb:BatchWriteItem","dynamodb:PutItem","dynamodb:UpdateItem","dynamodb:DeleteItem"],"Resource": [" arn:aws:dynamodb:us-east-1:123456789012:table/DemoTable "],"Effect": "Allow"}]
}

2.3 Keycloak 的设定

2.3.1 Keycloak 的安装

关于 Keycloak 的安装,请参照 blog:使用 SAML 和 Keycloak 建立 Amazon SSO 登陆 Console

2.3.2 Keycloak realm 的建立

Realm 可以理解为域,用于管理用户、用户凭据、角色和用户组。通常我们需要在 realm 里创建 client ,不同的应用客户端应在 realm 中配置不同的 client 。当进行鉴权时,请求资源的应用客户端会向鉴权服务器请求 Auth Code ,正如上文中 OAuth2.0鉴权流程 第2步所示。为了完成 Keycloak realm 的建立,我们可以:

  1. 登陆 keycloak admin console,点击 “Administration Console” 并登陆;

image.png

  1. 创建一个 realm,并进入到 realm 中;

image.png

2.3.3 Keycloak Client 的建立

  1. 在 realm 中点击 “Configure-> Clients-> Create”;

image.png

  1. 按照下面的说明输入相关信息;注意选择 Standard Flow Enabled,这将会使 client 的鉴权按照0的 “Authorization Code Flow” 完成,即 OAuth2.0鉴权流程所示。

注意,如没有特别的需求,尽量避免使用 “Implicit Flow” 即关闭 “Implicit Flow Enabled” 。这种方式没有授权码这个中间步骤,所以称为(授权码)”隐藏式”(implicit)。这将会把 Token 直接传给前端,是很不安全的,因此,只能用于一些安全要求不高的场景。

image.png

  1. 在 “Credentials tab” 中,选择 Client Id and Secret,此时会生成一串随机字符串作为Secret。在上文中 OAuth2.0鉴权流程 第6步中交换 Token 的过程中,Secret 将作为 client_secret 的值,在应用客户端的 POST Body 中被发送到 Keycloak Client 中,以确保向 Client 交换的 Token 颁布给了正确的应用客户端。

2.3.4 Keycloak User 的建立

  1. 创建测试用的 User,点击左侧 Manage-> Users-> Add user”;

image.png

  1. 输入 User 信息;

image.png

  1. 设定密码,输入密码,并输入 Password Confirmation,点击 Reset Password 以完成设置。

image.png

2.4 API Gateway Authorizer 的设定
  1. 进入到上文创建的 API Gateway 中,由于我们的目的是在创建 item 时,需要进行 API 鉴权,因此只在 POST /items 的路由上附加授权方即可:

image.png

  1. 输入相关信息;

image.png

  • 身份来源:通常情况下,在请求资源服务器时,会将 JWT Token 写入到请求头中的 Authorization 字段,因此可以保留默认。
  • 发布者 URL:针对 Keycloak 为https://{Keycloak_URL}/auth/realms/{realm}/
  • 受众:关联的受众,此处输入 account

3. 验证 JWT Authorizer

3.1 请求 Auth Code
  1. 根据 OAuth2.0鉴权流程,当用户请求资源时,应用客户端将会向鉴权服务器发送 GET 请求,以请求 Auth Code;
GET https://{Keycloak_URL}/auth/realms/Keycloaksso/protocol/openid-connect/auth?response_type=code&client_id=Keycloak

  1. 在此过程中,鉴权服务器将会返回 Keycloak 的登陆界面,要求用户输入其用户名密码,在此处,我们输入 Keycloak User 的建立章节中创建的 User 的用户名和密码。

image.png

  1. 输入正确的用户名和密码后,Keycloak 将会通过 Query String 返回 Auth Code,如下图所示;

image.png

3.2 交换 JWT Token
  1. 接下来,我们通过 Postman 模仿应用客户端,模拟通过 POST Auth Code 换取 JWT Token 的过程;

image.png

  • client_id: Keycloak的client ID,为 Keycloak Client 的建立 章节中创建;
  • grant_type: 0的鉴权模式,我们通过 authorization code 模式鉴权,这也是最常见的模式;
  • client_secret: 用于 Client 应用客户端的验证;
  • code:Auth Code,由鉴权服务器返回,用于交换 Token。
  1. 将 Postman 的请求用 curl 实现:
curl --location --request POST 'https://{Keycloak_URL}/auth/realms/Keycloaksso/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: AUTH_SESSION_ID=a0b56dbf-19b0-4d16-b254-c25248834c01.Keycloak-5b7448f8cf-v5wg6; AUTH_SESSION_ID_LEGACY=a0b56dbf-19b0-4d16-b254-c25248834c01.Keycloak-5b7448f8cf-v5wg6; KC_RESTART=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIyYjQ0M2Q2ZS00MzNiLTQwYTQtYjdlMi03MDk2Mjg1YTJkYmMifQ.eyJjaWQiOiJrZXljbG9hayIsInB0eSI6Im9wZW5pZC1jb25uZWN0IiwicnVyaSI6IioiLCJhY3QiOiJBVVRIRU5USUNBVEUiLCJub3RlcyI6eyJpc3MiOiJodHRwczovL2F1dGguY2lhdGVzdC50b3AvYXV0aC9yZWFsbXMva2V5Y2xvYWtzc28iLCJyZXNwb25zZV90eXBlIjoiY29kZSJ9fQ.5T6tBz-j7vbfzvhHBpPnQ2ebRqYC69gNF-EMlWmsA8Q' \
--data-urlencode 'client_id=Keycloak' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'client_secret=bba58d29-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
--data-urlencode 'code=74926370-xxxx-xxxx-xxxx-xxxxxxxxxxxx.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Response:

    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldU….eyJleHAiOjE2NTYyNDExOTksImlhdCI6MT….m91pmRMmSnA0D37qF4_...","expires_in": 300,"refresh_expires_in": 1800,"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldU….eyJleHAiOjE2NTYyNDI2OTksImlhdCI6MT….OaDarszhAnyd3NKZTiZ…","token_type": "Bearer","not-before-policy": 0,"session_state": "aa8b66e0-xxxx-xxxx-xxxx-6ff28b1213d5","scope": "profile email"
}

3.3 向 API Gateway 请求创建资源
  1. 通过 Postman 模仿应用客户端,模拟创建 item 的过程;

image.png

  • Authorization:将2中返回的 access_token 粘贴在 Authorization header 中,格式为:Bearer {access_token}
  1. 将 Postman 的请求用 curl 实现:
curl --location --request POST 'https://80iiueir8b.execute-api.us-east-1.amazonaws.com/items' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldU….eyJleHAiOjE2NTYyNDExOTksImlhdCI6MT….m91pmRMmSnA0D37qF4_...\
--header 'Content-Type: application/json' \
--data-raw '{"title":"nike high heel"}'

Response:

"New Item Created"

  1. 通过浏览器 GET /item 查看 item 是否写入成功:

image.png

4. 总结

由于当前 Cognito 在中国区仍不可用,Keycloak 可以作为一个替代方案,完成用户的单点登录和 API 的鉴权。本 blog 提供了如何结合 API Gateway 的 HTTP API,利用 Keycloak 和 JWT 进行 API 鉴权的演示。通过这种方式,应用客户端在请求 Amazon 资源时,需要通过 Keycloak 服务器进行校验,并换取有效的 JWT Token,以获得访问资源的权限。

如有兴趣了解本文提到的更多技术,请参照:

OAuth2.0 Grant Type

Json Web Token

使用 SAML 和 Keycloak 建立 Amazon SSO 登录 Console

How to secure API Gateway HTTP endpoints with JWT authorizer

本篇作者

李潇翌 亚马逊云科技专业服务团队安全顾问,负责云安全合规、云安全解决方案等的咨询设计及落地实施,致力于为客户上云提供安全最佳实践,并解决客户上云中碰到的安全需求。

文章来源:https://dev.amazoncloud.cn/column/article/630b4bf9269604139cb5e9ed?sc_medium=regulartraffic&sc_campaign=crossplatform&sc_channel=CSDN

相关文章:

通过 Keycloak 结合 OAuth2.0协议进行 Amazon API Gateway 鉴权

1. 简介 本文介绍了如何通过 Keycloak,并结合 Amazon API Gateway 内置的授权功能,完成对 Amazon 资源请求的鉴权过程。API Gateway 帮助开发者安全的的创建、发布、维护并管理 API 的访问。在中国区,由于Cognito 仍未上线,因此使…...

修复中间件log4j漏洞方案(直接更换漏洞jar包)

说明: 后台服务里面的log4j漏洞我们已经全部升级处理了,但是一些中间件镜像包里的log4j漏洞需要单独处理 解决办法以ElasticSearch7.6.2为例: 方法: (1)找到容器里面有哪些旧的log4j依赖包 (…...

怎么压缩pdf文件大小?详细压缩步骤

怎么压缩pdf文件大小?在日常的工作和学习中,我们频繁地处理PDF文件。然而,有时候这些文件的大小可能会非常庞大,这给我们带来了一系列的问题。首先,它们占用了大量的存储空间,使得我们的设备变得拥挤不堪。…...

php 安装rabbitmq:如何使用 PHP 安装 RabbitMQ?

示例示例安装Erlang要在PHP环境中使用,需要先安装Erlang,它是的运行环境。 1、安装Erlang 首先,要在PHP环境中使用RabbitMQ,需要先安装Erlang,它是RabbitMQ的运行环境。 可以使用下面的命令来安装Erlang&#xff1a…...

算法训练营day44|动态规划 part06:完全背包 (完全背包、 LeetCode518. 零钱兑换 II、377. 组合总和 Ⅳ )

文章目录 完全背包518. 零钱兑换 II (求组合方法数)思路分析代码实现思考总结 377. 组合总和 Ⅳ (求排列方法数)思路分析代码实现思考总结 完全背包 完全背包和01背包问题唯一不同的地方就是,每种物品有无限件。 依然举这个例子: 背包最大重量为4。 物…...

包管理工具--》其他包管理器之cnpm、pnpm、nvm

包管理工具系列文章目录 一、包管理工具--》npm的配置及使用(一) 二、包管理工具--》npm的配置及使用(二) 三、包管理工具--》发布一个自己的npm包 四、包管理工具--》yarn的配置及使用 五、包管理工具--》其他包管理器之cnpm…...

线性代数的学习和整理22:矩阵的点乘(草稿)

4 矩阵乘法 A,B两个同阶同秩N阵,看上去结构一样,但两厢相乘,在做在右,地位差别巨大。 在左,你就是基,是空间的根本,是坐标系,是往哪去、能到哪的定海神针,是如来佛手&a…...

如何在Windows中使用C#填写和提取PDF表单

如何在Windows中使用C#填写和提取PDF表单 PDF表单不仅允许用户填写和提交数据,也允许用户创建各种表单域收集用户的数据,并通过提取表单字段值,将收集和合并提交的数据进一步分析或处理。PDF通过电子方式填写、保存和共享的形式,…...

microsoft.office.interop.word 怎样 读取 某个汉字 字体颜色为红色

SKY[管理]筱傑 SKY[机器]筱淋 microsoft.office.interop.word 怎样 读取 某个汉字 字体颜色为红色呢? 要读取某个汉字的字体颜色是否为红色,您可以使用Microsoft.Office.Interop.Word来进行操作。以下是一个示例代码,可以帮助您实现该功能&am…...

第二十二章 Classes - 调用类方法的快捷方式

文章目录 第二十二章 Classes - 调用类方法的快捷方式调用类方法的快捷方式类参数 第二十二章 Classes - 调用类方法的快捷方式 调用类方法的快捷方式 使用 ObjectScript 调用类方法时,在以下情况下可以省略包(或更高级别的包):…...

标准C++day2——函数重载、默认形参和引用

一、函数重载 1、什么是函数重载? 在同一作用域下,函数名相同,参数列表不同的函数构成重载关系 函数重载与返回值类型、参数名无关 与作用域是否相同,以及参数列表的数量、参数类型、常属性不同等有关 2、C是如何实现函数重载的&a…...

Qt5下遍历QList的方法

lines定义如下 QMap<QString,Line> lines; Line的定义如下 class Line{protected:QString name;QColor color;QList<int> total_stations; // all statuibQList<QString> start_stas,end_stas; //start end stationQList<QList<QString>>sta_li…...

Leetcode 剑指 Offer II 043. 完全二叉树插入器

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 完全二叉树是每一层&#xff08;除最后一层外&#xff09;都是完…...

链路追踪Skywalking应用实战

目录 1 Skywalking应用2 agent下载3 agent应用3.1 应用名配置3.2 IDEA集成使用agent3.3 生产环境使用agent 4 Rocketbot4.1 Rocketbot-仪表盘4.2 Rocketbot-拓扑图4.3 追踪4.4 性能分析4.5 告警4.5.1 警告规则详解4.5.2 Webhook规则4.5.3 自定义Webhook消息接收 1 Skywalking应…...

提升你的Android开发技能:从AR/VR沉浸到UI设计和故障排除

文章目录 探索最新AR/VR应用在教育、游戏、医疗等领域的应用教育领域游戏领域医疗领域 深入了解Android内存管理与性能优化的方法与技巧垃圾回收机制内存泄漏使用弱引用避免过度渲染内存优化图像优化延迟加载Android中的调试技术应用程序分析 分享如何提高Android应用的易用性和…...

Arm 架构 Ubuntu 使用 Docker 安装 Gitlab 并使用

官方 gitlab 文档 我的系统是 arm 架构的 ubuntu 官网没有提供 arm 架构的 docker 的 gitlab 的安装方式&#xff0c;直接安装的也是后来加的&#xff0c;文档也是随笔带过&#xff0c;&#xff0c;&#xff0c;我用到了&#xff0c;记录一下 默认已经安装了 docker 在 docker …...

百度地图3D棱柱鼠标事件

百度地图2D API JavaScript API | 百度地图API SDK 百度地图3D API jspopularGL | 百度地图API SDK 3D棱柱效果如下 一. 渲染地图 var map new BMapGL.Map(container, {style: {styleJson: styleJson2} }) map.centerAndZoom(new BMapGL.Point(116.404, 39.925), 9); map…...

PHP调用java class 类实现文件签名

PHP调用java class 类实现文件签名 原始代码改造开始PHP内调用方式起因:对接某平台API接口,发送的文件需要做 SM3 签名,对方平台是java写的,只有java加密示例,照着java的加密算法翻译为PHP版本,在编码转换上始终有些差异。没办法,只能想办法使用他们的java方式。 原始代…...

信号和槽机制

信号和槽机制 信号和槽的使用自定义信号槽信号槽机制是Qt框架中引以为豪机制之一,所谓信号槽实际就是类似于Gof中的观察者模式。当某个事件发生以后,比如点击一下按钮,按钮就会触发一个信号,这个信号按照类似广播的形式进行发送,如果某个对象对这个信号感兴趣就会触发连接…...

计算机视觉领域经典模型汇总(2023.09.08

一、RCNN系列 1、RCNN RCNN是用于目标检测的经典方法&#xff0c;其核心思想是将目标检测任务分解为两个主要步骤&#xff1a;候选区域生成和目标分类。 候选区域生成&#xff1a;RCNN的第一步是生成可能包含目标的候选区域&#xff0c;RCNN使用传统的计算机视觉技术&#x…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...