Apache SeaTunnel Zeta Engine 的 Basic Auth 是怎么工作的?

最近在看 Apache SeaTunnel Zeta Engine 的 REST API 认证逻辑时,遇到一个很典型的问题。
178237385855552b03a3968dd6297

https://github.com/apache/SeaTunnel

点击蓝字



关注我们


最近在看 Apache SeaTunnel Zeta Engine 的 REST API 认证逻辑时,遇到一个很典型的问题:

Zeta Engine 明明已经启动了,REST 服务也正常监听端口,但是访问 /overview/running-jobs/job-info 这些接口时,却返回了:


HTTP/1.1 401 Unauthorized

如果只是第一次看到这个错误,很容易以为是服务没有启动、端口写错了,或者接口路径不对。

但实际上,这类 问题很多时候和 SeaTunnel Zeta Engine 的 Basic Auth 配置有关。

当 Zeta Engine 开启 Basic Auth 后,客户端再访问 REST API,就不能像之前一样直接请求接口,而是必须在请求头里带上正确的认证信息。

这篇文章就从这个 401 问题开始,简单看一下 SeaTunnel Zeta Engine 的 Basic Auth 是怎么工作的,以及客户端应该如何正确连接。

1. 先说现象:访问 Zeta REST API 返回 401

假设我们直接访问 Zeta Engine 的 REST API:


curl http://localhost:8080/overview

如果没有开启 Basic Auth,这个请求可以正常返回 Zeta Engine 的概要信息。

但是当配置里开启 Basic Auth 后,如果请求没有携带认证信息,就会返回:



HTTP/1.1 401 UnauthorizedWWW-Authenticate: Basic realm="SeaTunnel Web UI"

这说明请求已经到达了 Zeta Engine,但在进入真正的 REST Servlet 之前,被认证过滤器拦截了。

也就是说:





Zeta Engine 正常运行REST API 地址也没有问题但是客户端没有带 Authorization 请求头所以被 BasicAuthFilter 拦截并返回 401

Basic Auth 本身并不复杂,它本质上就是在 HTTP Header 中增加一段认证信息:


Authorization: Basic base64(username:password)

例如用户名是 admin,密码是 admin,客户端最终需要把:


admin:admin

做 Base64 编码,然后放到 Authorization 请求头里。

2. 看源码:BasicAuthFilter

如何拦截请求

SeaTunnel Zeta Engine 的 Basic Auth 核心逻辑在 BasicAuthFilter 中。

这个类实现了标准的 Servlet Filter







public class BasicAuthFilter implements Filter {    private final HttpConfig httpConfig;    public BasicAuthFilter(HttpConfig httpConfig) {        this.httpConfig = httpConfig;    }}

Filter 的特点是:请求进入真正的 Servlet 之前,会先经过过滤器。

所以 Basic Auth 的认证逻辑并不是写在某一个具体接口里,而是在统一的过滤器中完成的。

核心代码在 doFilter 方法里。

首先,它会判断是否开启 Basic Auth:





if (!httpConfig.isEnableBasicAuth()) {    chain.doFilter(request, response);    return;}

这段代码很关键。

如果没有开启 Basic Auth,请求会直接放行:


chain.doFilter(request, response);

也就是说,enable-basic-auth 没有开启时,REST API 不需要认证。

如果开启了 Basic Auth,代码会继续往下走,开始读取 HTTP 请求头:




HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;String authHeader = httpRequest.getHeader("Authorization");

然后判断请求头是否存在,并且是否以 Basic 开头:







if (authHeader != null && authHeader.startsWith("Basic ")) {    String base64Credentials = authHeader.substring("Basic ".length());    String credentials =            new String(Base64.decodeBase64(base64Credentials), StandardCharsets.UTF_8);    final String[] values = credentials.split(":", 2);}

这里做了几件事:

  1. 从请求头中取出 Authorization
  2. 去掉前面的 Basic
  3. 对后面的内容进行 Base64 解码
  4. 将解码后的字符串按 : 拆分成用户名和密码

比如请求头是:


Authorization: Basic YWRtaW46YWRtaW4=

解码后就是:


admin:admin

然后代码会和配置中的用户名、密码进行比较:






if (username.equals(httpConfig.getBasicAuthUsername())        && password.equals(httpConfig.getBasicAuthPassword())) {    chain.doFilter(request, response);    return;}

如果用户名和密码都正确,请求继续放行。

如果请求头不存在、格式不正确、用户名密码不匹配,就会返回 401:



httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"SeaTunnel Web UI\"");httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");

所以 BasicAuthFilter 的整体流程可以理解成:















请求进入 Zeta REST 服务        ↓判断是否开启 Basic Auth        ↓未开启:直接放行        ↓已开启:读取 Authorization 请求头        ↓解析 Basic Auth 用户名和密码        ↓和配置中的 username/password 比较        ↓匹配成功:放行匹配失败:返回 401 Unauthorized

3. 看配置:enable-basic-auth、

username、password 如何生效

Basic Auth 相关的核心配置主要有三个:

1782373859820ff663b44f471060e

也就是说,默认情况下:




enable-basic-auth = falsebasic-auth-username = adminbasic-auth-password = admin

这里要注意一点:

虽然 basic-auth-username basic-auth-password 默认都是 admin,但是如果 enable-basic-auth 没有开启,它们并不会生效。

真正决定是否启用认证的是:


enable-basic-auth

如果它是 false,Zeta Engine 的 REST API 不会要求客户端携带 Basic Auth。

如果它是 true,所有被 BasicAuthFilter 保护的请求都需要认证。

一个示例配置大概是这样:












seatunnel {  engine {    http {      enable-http = true      port = 8080      enable-basic-auth = true      basic-auth-username = "admin"      basic-auth-password = "admin"    }  }}

开启后,普通请求就会失败:


curl http://localhost:8080/overview

返回:


401 Unauthorized

正确的访问方式应该是:


curl -u admin:admin http://localhost:8080/overview

或者显式传递 Header:




curl \  -H "Authorization: Basic YWRtaW46YWRtaW4=" \  http://localhost:8080/overview

这里的 YWRtaW46YWRtaW4= 就是 admin:admin 的 Base64 编码。

4. 看客户端:如何通过

Authorization Header 连接

理解了服务端的认证逻辑后,客户端要做的事情就很明确了:

只要 Zeta Engine 开启了 Basic Auth,客户端请求 REST API 时,就必须带上:


Authorization: Basic base64(username:password)

如果用 Java 代码访问,可以直接使用 Spring 的 HttpHeaders#setBasicAuth

例如:










HttpHeaders headers = new HttpHeaders();headers.setBasicAuth("admin", "admin", StandardCharsets.UTF_8);HttpEntity<Void> entity = new HttpEntity<>(headers);ResponseEntity<Map> response = restTemplate.exchange(        "http://localhost:8080/overview",        HttpMethod.GET,        entity,        Map.class);

这段代码会自动生成 Basic Auth 请求头,不需要我们手动做 Base64 编码。

如果想封装得更通用一点,可以把认证逻辑独立成一个方法:














private void applyBasicAuth(HttpHeaders headers, String username, String password) {    if (username == null || username.trim().isEmpty()) {        return;    }    if (password == null || password.trim().isEmpty()) {        return;    }    headers.setBasicAuth(            username.trim(),            password,            StandardCharsets.UTF_8    );}

然后每次请求 Zeta REST API 前,都统一调用:




HttpHeaders headers = new HttpHeaders();headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));applyBasicAuth(headers, username, password);

这样无论是 GET 请求:







restTemplate.exchange(        "http://localhost:8080/running-jobs",        HttpMethod.GET,        new HttpEntity<Void>(null, headers),        List.class);

还是 POST 请求:







restTemplate.exchange(        "http://localhost:8080/submit-job",        HttpMethod.POST,        new HttpEntity<>(configText, headers),        Map.class);

都可以统一带上认证信息。

这也是客户端连接开启 Basic Auth 的 Zeta Engine 时最核心的一点:

  1. 不是 REST API 变了
  2. 也不是接口路径变了
  3. 只是请求头中必须多一个 Authorization

    5. 最后补充:SeaTunnel Web 如何把这一步可视化

17823738603514ca287b2fb544d46

前面讲的是 SeaTunnel Zeta Engine 层面的 Basic Auth 逻辑。

如果直接用代码连接,我们需要自己维护:






Zeta Engine 地址端口是否开启 Basic Auth用户名密码

然后在每次请求 REST API 时,把认证信息加到请求头里。

但对于很多使用者来说,他们并不希望每次都手动写代码、拼 Header、测试接口。

所以在 SeaTunnel Web 中,可以把这一步做成可视化配置。

比如新增一个 Zeta Engine 客户端时,页面上可以提供这些配置项:








Client NameEngine TypeClient AddressClient PortEnable Basic AuthUsernamePassword

当用户开启 Basic Auth,并填写用户名密码后,SeaTunnel Web 在请求 Zeta REST API 时,自动补充:


Authorization: Basic xxx

这样用户点击“测试连接”时,背后实际访问的还是 Zeta Engine 的 /overview 接口,只是 SeaTunnel Web 帮用户把认证请求头处理好了。

保存客户端后,后续访问这些接口:









/overview/running-jobs/job-info/finished-jobs/submit-job/submit-job/upload/stop-job/metrics

也都可以基于保存的客户端配置,自动带上 Basic Auth。

这样做的好处是:

  1. SeaTunnel Zeta Engine 仍然保持原有的 REST 认证机制
  2. SeaTunnel Web 只是把认证配置可视化
  3. 用户不需要关心 Authorization Header 的细节


小结

SeaTunnel Zeta Engine 的 Basic Auth 逻辑并不复杂,但它很容易在第一次使用时造成 401 问题。

核心可以总结成几句话:

  1. enable-basic-auth

    默认是 false,不开启时 REST API 不需要认证。
  2. 开启 Basic Auth 后,Zeta Engine 会通过 BasicAuthFilter 拦截请求。
  3. 客户端必须在请求头中携带 Authorization: Basic xxx
  4. xxx

    username:password 的 Base64 编码。
  5. basic-auth-username

    basic-auth-password 默认都是 admin
  6. SeaTunnel Web 可以把这个过程可视化,让用户通过页面配置完成认证连接。

所以,当我们遇到:


401 Unauthorized

不要第一时间怀疑 Zeta Engine 没启动,也不要只看端口和接口路径。

更应该先确认:

  1. 是否开启了 enable-basic-auth
  2. 客户端是否带了 Authorization 请求头
  3. 用户名和密码是否和配置一致

理解了这一点,再看 SeaTunnel Zeta Engine 的 REST API 认证流程,就会清楚很多。

原文链接:https://blog.csdn.net/weixin_41572727/article/details/161571362

Apache SeaTunnel

Apache SeaTunnel是一个云原生的多模态、高性能海量数据集成工具。北京时间 2023 年 6 月1 日,全球最大的开源软件基金会ApacheSoftware Foundation正式宣布SeaTunnel毕业成为Apache顶级项目。目前,SeaTunnel在GitHub上Star数量已达9k+。SeaTunnel支持在云数据库、本地数据源、SaaS、大模型等170多种数据源之间进行数据实时和批量同步,支持CDC、DDL变更、整库同步等功能,更是可以和大模型打通,让大模型链接企业内部的数据。




同步Demo

MySQL→Doris | MySQLCDC | MySQL→Hive | HTTP → Doris | HTTP → MySQL | MySQL→StarRocks|MySQL→Elasticsearch |Kafka→ClickHouse

新手入门

SeaTunnel 让数据集成变得 So easy!/ 3 分钟入门指南
0 到 1 快速入门 /初探/深入理解
分布式集群部署 | CDC数据同步管道 | Oracle-CDC
图片

最佳实践

中控技术天翼云多点OPPO | 清风马蜂窝孩子王哔哩哔哩唯品会众安保险兆原数通 | 亚信科技|映客|翼康济世|信也科技|华润置地|Shopee|京东科技|58同城|互联网银行|JPMorgan
图片

测试报告

SeaTunnel VS GLUE | VS Airbyte | VS DataX|SeaTunnel 与 DataX 、Sqoop、Flume、Flink CDC 对比
图片

源码解析

Zeta引擎源码解析(一) |(二) |(三)| API 源码解析 |2.1.1源码解析|封装 Flink 连接数据库解析





仓库地址:
https://github.com/apache/seatunnel
网址:
https://seatunnel.apache.org/
Apache SeaTunnel 下载地址:
https://seatunnel.apache.org/download
衷心欢迎更多人加入!
我们相信,在Community Over Code(社区大于代码)、「Open and Cooperation」(开放协作)、「Meritocracy」(精英管理)、以及「多样性与共识决策」The Apache Way 的指引下,我们将迎来更加多元化和包容的社区生态,共建开源精神带来的技术进步!
我们诚邀各位有志于让本土开源立足全球的伙伴加入 SeaTunnel 贡献者大家庭,一起共建开源!
提交问题和建议:
https://github.com/apache/seatunnel/issues
贡献代码:
https://github.com/apache/seatunnel/pulls
订阅社区开发邮件列表 :
dev-subscribe@seatunnel.apache.org
开发邮件列表:
dev@seatunnel.apache.org
加入 Slack:
https://join.slack.com/t/apacheseatunnel/shared_invite/zt-3uouszk3m-PtLLNyZsJVqE5Gb6gn24mA
关注 X.com:
https://x.com/ASFSeaTunnel


1782373862770a9d9dfb380e33dab
178237386344707a26525f5d4ce52
17823738642122fe8a1d1e5050dd4