多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Envoy Basic Auth 过滤器实战指南:配置、源码原理与每路由鉴权

Envoy Basic Auth 过滤器实战指南:配置、源码原理与每路由鉴权 Envoy Basic Auth 过滤器实战指南配置、源码原理与每路由鉴权【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoyBasic Auth 是 Envoy 内置的 HTTP 过滤器用于解析并校验 RFC 7617 为核心骨架结合 Envoy 仓库内过滤器源码basic_auth_filter.cc、配置工厂config.cc、API 定义basic_auth.proto与单元测试filter_test.cc完整讲解过滤器配置、htpasswd 用户文件格式、认证判定流程、每路由级鉴权覆盖与统计指标帮助你直接在 Envoy 中落地一套可复制的 HTTP Basic Auth 鉴权方案。过滤器是什么Basic Auth 过滤器是一个 HTTP解码路径过滤器decoder filter它拦截进入的请求头decodeHeaders阶段从 HTTPAuthorization头中提取用户名和密码与过滤器配置中预置的用户名-密码列表逐一比对用户名和密码有效请求被放行继续传递到过滤链中的下一个过滤器用户名和密码无效或缺失请求被拒绝返回401 Unauthorized响应并附带符合 RFC 7617 的WWW-Authenticate挑战头。从源码结构看过滤器的核心实现位于source/extensions/filters/http/basic_auth/通过BasicAuthFilter::decodeHeaders完成全部判定逻辑过滤器注册名称为envoy.filters.http.basic_auth见 well_known_names.h对应扩展类型 URL 为type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuthAPI 版本为 v3见 basic_auth.proto 中的[#extension: envoy.filters.http.basic_auth]标记。过滤器配置type URL 与 users 字段过滤器通过 HTTP 过滤链中的typed_config完成配置type URL 固定为type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuth核心字段users是一个用户名-密码对列表用于校验请求Authorization头中的用户凭据。它的取值需要符合htpasswd工具的输出格式Apache HTTP Server 的密码文件格式users字段类型为config.core.v3.DataSource既可以内联提供也可以指向磁盘上的文件详见 basic_auth.proto 第 37 行且该字段被标记为sensitive即敏感字段。最小可运行配置示例以下配置来自 basic_auth_filter.rst可直接放入http_filters过滤链通常放在router过滤器之前http_filters: - name: envoy.filters.http.basic_auth typed_config: type: type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuth users: inline_string: |- user1:{SHA}hashed_user1_password user2:{SHA}hashed_user2_password注意inline_string中使用|-块标量保留换行格式文件每行一条用户记录格式为用户名:{SHA}哈希值。目前过滤器仅支持{SHA}格式即 Base64 编码的 SHA-1 摘要文档明确指出其他格式可能在未来加入。更完整的字段级配置除users外BasicAuth消息还提供了四个可选字段均定义于 basic_auth.proto 第 3374 行字段类型默认行为说明usersDataSource敏感必填htpasswd 格式的用户名-密码对内联或引用文件forward_username_headerstring不转发认证成功后将用户名以该请求头名注入到转发给后端的请求中留空则不转发authentication_headerstringAuthorization指定从哪个请求头读取 Basic 凭据留空则读取Authorizationallow_missingboolfalse为true时缺失凭据无Authorization头或头不是Basicscheme的请求被放行但已携带 Basic 凭据的请求仍会严格校验emit_dynamic_metadataboolfalse认证成功后向动态元数据dynamic metadata写入 key 为username的字段命名空间为过滤链中配置的过滤器名称其中forward_username_header与authentication_header在 proto 中都带HTTP_HEADER_NAME校验规则非严格模式确保填写的必须是合法 HTTP 头名。一个同时使用这些字段的示例http_filters: - name: envoy.filters.http.basic_auth typed_config: type: type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuth users: filename: /etc/envoy/htpasswd.users forward_username_header: x-auth-user authentication_header: authorization allow_missing: false emit_dynamic_metadata: true需要说明的是users使用filename时文件内容由Config::DataSource::read在过滤器工厂创建时读取见 config.cc 第 70 行因此修改密码文件后需要触发配置热更新如 xDS 推送或重启才能生效而 per-route 的users则是在路由匹配时按需读取同文件第 88 行传入了true。htpasswd 用户文件格式源码级解析规则过滤器对用户列表的解析实现在readHtpasswd函数中config.cc 第 1663 行。了解这些规则有助于你写出合法、不会导致配置加载失败的 htpasswd 文件逐行解析使用:作为用户名与密码哈希的分隔符跳过空行以及#开头的注释行源码注释中保留了一个 TODO未来可能考虑修剪行首行尾空格格式非法行内没有:会直接返回错误错误信息为basic auth: invalid htpasswd format, username:password is expected用户名或哈希为空同样报错重复用户名会报duplicate users错误——用户表中不允许同名用户哈希必须带{SHA}前缀否则报错unsupported htpasswd format: please use {SHA}{SHA}之后的 Base64 字符串长度必须为 28 个字符Base64 编码的 SHA-1 摘要恰好为 28 字节文本长度不符直接报错。因此一个合法的 htpasswd 文件形如# 注释行会被忽略 user1:{SHA}tESsBmE/yNY3lb6a0L6vVQEZNqw user2:{SHA}EJ9LPFDXsN9ynSmbxvjp75Bmlx8上面两个哈希值正是单元测试中使用的样例filter_test.cc 第 2223 行分别对应明文密码test1与test2可作为自测基准。{SHA}哈希的生成方式与过滤器内部校验逻辑一一对应computeSHA1basic_auth_filter.cc 第 2533 行对明文密码计算 SHA-1 摘要再对 20 字节的二进制摘要做 Base64 编码。你可以用任意支持 SHA-1 Base64 的工具例如htpasswd -bn user pass或openssl dgst -sha1 -binary | base64生成同格式的哈希。常量时间比较值得注意的实现细节是密码比对使用了 OpenSSL 的CRYPTO_memcmpbasic_auth_filter.cc 第 124 行且在比较前先校验长度是否一致第 121122 行。这是一种常量时间比较constant-time comparison做法可以降低基于响应时间差异的时序侧信道攻击风险先比长度也能避免对长度不匹配的字符串进行无谓的哈希比较。认证判定流程源码调用链剖析过滤器在请求头阶段decodeHeaders完成全部认证逻辑basic_auth_filter.cc 第 48110 行完整流程如下解析每路由覆盖配置通过Http::Utility::resolveMostSpecificPerFilterConfig获取当前路由的FilterConfigPerRoute若存在则用路由级用户表替换全局用户表第 4954 行定位认证头若配置了authentication_header从该头读取凭据否则读取标准Authorization头第 5661 行凭据缺失处理Authorization头不存在时——若allow_missing为true直接放行否则以no_credential_for_basic_auth拒绝第 6369 行Scheme 校验凭据必须以Basic前缀开头区分大小写。非 Basic scheme如Bearer时allow_missingtrue放行否则以invalid_scheme_for_basic_auth拒绝第 7379 行Base64 解码去掉Basic前缀后对剩余 token 做无填充 Base64 解码第 8184 行切分用户名/密码解码后的字符串格式为username:password以第一个:切分找不到冒号则以invalid_format_for_basic_auth拒绝第 8694 行凭据校验validateUser在用户表中查找用户名对密码计算{SHA}哈希并与存储值做常量时间比较失败以invalid_credential_for_basic_auth拒绝第 9699 行实现见第 112125 行成功后处理若配置了forward_username_header把用户名写入该请求头后转发给上游若开启emit_dynamic_metadata将username写入 stream 的动态元数据命名空间为过滤链中的过滤器名称allowed计数器 1 并放行第 101109 行。401 响应与 WWW-Authenticate 挑战头当认证失败时onDenied第 135150 行会使denied计数器 1调用sendLocalReply返回401 Unauthorized响应体为对应的失败原因文本构造WWW-Authenticate: Basic realm原始URI响应头其中 URI 由请求头重建最多截取 256 字符MaximumUriLength常量让浏览器等客户端可以弹窗重新提示输入凭据返回StopIteration终止后续过滤器处理。单元测试对此有明确断言filter_test.cc 第 113126 行对http://host/的请求失败响应的WWW-Authenticate头值为Basic realmhttp://host/同时携带details字段invalid_credential_for_basic_auth等这些 details 会被记录到访问日志方便排查认证失败原因。每路由Per-Route配置Basic Auth 过滤器支持在路由、虚拟主机或加权集群级别覆盖认证配置实现同一条过滤链、不同路径不同鉴权策略。其类型 URL 为type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuthPerRouteBasicAuthPerRoute消息仅有一个必填字段users类型 DataSource标记为敏感字段见 basic_auth.proto 第 7882 行即只覆盖用户表不覆盖其他字段。从源码看路由级配置通过BasicAuthFilterFactory::createRouteSpecificFilterConfigTyped构建为FilterConfigPerRouteconfig.cc 第 8493 行并在每次请求的decodeHeaders开头被解析basic_auth_filter.cc 第 4954 行。官方示例定制用户 关闭鉴权以下示例来自 basic_auth_filter.rst 的 Per-Route Configuration 章节演示两种典型场景为/admin路径定制专属用户以及对/static前缀路径关闭认证route_config: name: local_route virtual_hosts: - name: local_service domains: [*] routes: - match: { path: /admin } route: { cluster: some_service } typed_per_filter_config: envoy.filters.http.basic_auth: type: type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuthPerRoute users: inline_string: |- admin:{SHA}hashed_admin_password - match: { prefix: /static } route: { cluster: some_service } typed_per_filter_config: envoy.filters.http.basic_auth: type: type.googleapis.com/envoy.config.route.v3.FilterConfig disabled: true - match: { prefix: / } route: { cluster: some_service }解读/admin路由通过BasicAuthPerRoute覆盖该路径的用户表只有admin用户能访问/static前缀路由使用type.googleapis.com/envoy.config.route.v3.FilterConfig且disabled: true直接禁用该过滤器静态资源无需认证其余/前缀路由不配置typed_per_filter_config回落到过滤链级别的全局用户表。路由级配置遵循 Envoy 标准的最具体配置优先most specific per filter config解析语义因此你可以按route - virtual host - weighted cluster的粒度层层覆盖用户表。全局过滤链级的users是兜底只有未被路由配置覆盖的请求才使用它。与 JWT 等其他认证方法组合OR 语义allow_missing与emit_dynamic_metadata两个字段的组合是 Basic Auth 过滤器与其他认证过滤器如 JWT叠加、实现任一认证通过即可放行OR 语义的关键API 文档对此有明确设计说明见 basic_auth.proto 第 5273 行注释当allow_missing为true时缺失凭据或非 Basic scheme 的请求不会被拒绝而是放行到链中后续的认证过滤器例如 JWT 过滤器但携带了 Basic 凭据的请求仍会严格校验不会因为allow_missing而被绕过为了防止所有认证过滤器都因缺失凭据而放行、导致请求完全未认证的漏洞需要配合emit_dynamic_metadata: true——认证成功时过滤器把username写入动态元数据再在链尾配置一个 RBAC 过滤器rbac_filter.rst根据动态元数据中是否存在username来放行请求从而保证至少有一种认证方式成功。动态元数据的命名空间等于过滤链中该过滤器的名称默认即envoy.filters.http.basic_auth写入的 key 为username见 basic_auth_filter.cc 第 127133 行DynamicMetadataUsernameKey常量。单元测试验证了这一点emit_dynamic_metadata开启时认证成功后元数据中包含username: user1而默认关闭时不会写入任何元数据filter_test.cc 第 6298 行。统计指标Basic Auth 过滤器在http.stat_prefix.basic_auth.命名空间下输出两项计数器统计见 basic_auth_filter.rst 的 Statistics 章节stat_prefix来自过滤链的通用配置前缀名称类型描述allowedCounter通过认证、被放行的请求总数deniedCounter被拒绝的请求总数这两项计数器的定义位于 basic_auth_filter.h 第 1928 行的ALL_BASIC_AUTH_STATS宏在FilterConfig构造时以stats_prefix basic_auth.为前缀注册basic_auth_filter.cc 第 44 行。递增时机分别在认证成功放行前第 108 行与onDenied中第 137 行。你可以通过这两个指标观察认证拒绝率作为告警与容量规划的输入。测试用例验证仓库的单元测试与集成测试覆盖了过滤器的主要行为可作为你验证自身配置行为的参照filter_test.cc465 行覆盖正确凭据放行、错误用户拒绝、错误密码拒绝、x-username转发头注入、动态元数据写入、401 响应头与 details 断言等config_test.cc覆盖 htpasswd 解析的合法性校验重复用户、非法格式、{SHA}前缀、哈希长度等basic_auth_integration_test.cc端到端验证过滤器在真实 HTTP 链路中的表现。相关文件速查官方文档basic_auth_filter.rstAPI 定义basic_auth.proto过滤器实现basic_auth_filter.cc、basic_auth_filter.h配置工厂与 htpasswd 解析config.cc单元/集成测试filter_test.cc、config_test.cc、basic_auth_integration_test.cc结合官方配置示例与上述源码实现你可以在 Envoy 中快速启用全局 Basic Auth 鉴权、按路由定制用户甚至局部禁用认证并通过统计指标与访问日志中的 details 字段持续观测认证效果。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表