4. SASL/PLAIN 认证:从原理到实战

好,咱们今天来啃一块硬骨头——SASL/PLAIN 认证。说实话,这是 Kafka 安全里最基础、也最容易踩坑的认证方式。我最早接触 Kafka 安全时,第一个上手的就是它。为什么?因为简单、直接,适合快速搭建安全环境。

但简单不代表不重要。你想想看,很多生产环境的第一道防线,就是靠 PLAIN 撑起来的。咱们今天就把它的底裤扒干净。

4.1 SASL 机制:Kafka 的认证框架

SASL,全称 Simple Authentication and Security Layer。说白了,它就是一个认证框架,不是具体的认证算法。就像插座一样,你插什么电器,它就提供什么功能。

Kafka 支持这么几种 SASL 机制:

机制 特点 适用场景
PLAIN 明文传输用户名/密码 内网、测试环境、快速部署
SCRAM 加密传输,密码不暴露 生产环境,安全性更高
GSSAPI 基于 Kerberos 大型企业,已有 Kerberos 基础设施
OAUTHBEARER 基于 OAuth 2.0 云原生、微服务架构

我个人习惯,如果只是内部测试或者开发环境,PLAIN 就够了。但生产环境,我建议至少上 SCRAM。不过今天咱们只聊 PLAIN,其他机制后面章节会逐个拆解。

4.2 PLAIN 认证原理:到底怎么工作的?

PLAIN 认证的原理,用一句话概括就是:客户端把用户名和密码明文发给 Broker,Broker 去验证。

嗯,这里要注意——明文传输。所以 PLAIN 必须配合 SSL/TLS 加密通道使用,否则密码等于裸奔。我曾经见过一个团队,只配了 PLAIN 没配 SSL,结果安全审计直接挂了。

具体流程是这样的:

  1. 客户端发起连接请求,告诉 Broker "我要用 SASL/PLAIN"
  2. Broker 回复 "好,把你的凭证拿来"
  3. 客户端发送用户名 + 密码(明文)
  4. Broker 拿着凭证去 JAAS 配置文件里找匹配项
  5. 匹配成功 → 认证通过;匹配失败 → 连接断开

核心要点:PLAIN 认证不涉及任何加密算法,就是简单的字符串比对。所以它的性能开销极低,但安全性完全依赖传输层加密。

下面这张图,把整个流程画清楚了:

SASL/PLAIN 认证流程 客户端 Broker JAAS 配置 ① 连接请求 (SASL/PLAIN) ② 请求凭证 ③ 发送用户名 + 密码 (明文) ④ 验证 ⑤ 返回结果 通过 / 拒绝

避坑提醒:我曾经在生产环境遇到过一个问题——客户端一直连不上,日志里报 "Authentication failed"。查了半天,发现是 JAAS 文件里用户名写了个空格。PLAIN 认证对空格、大小写极其敏感,配置时一定要仔细。

4.3 Broker 端配置:手把手教你配

Broker 端的配置,核心就两步:写 JAAS 文件 + 改 server.properties。咱们一步步来。

4.3.1 创建 JAAS 配置文件

JAAS 文件是 Kafka 的认证凭证仓库。PLAIN 模式下,它就是一个用户名密码的映射表。

创建一个文件,比如 kafka_server_jaas.conf,内容如下:

KafkaServer {
  org.apache.kafka.common.security.plain.PlainLoginModule required
  username="admin"
  password="admin-secret"
  user_admin="admin-secret"
  user_producer="producer-secret"
  user_consumer="consumer-secret";
};

解释一下:

  • username 和 password:Broker 内部节点间通信用的凭证
  • user_xxx:定义客户端用户,格式是 user_用户名="密码"
  • 分号结尾,不能漏

注意:JAAS 文件里不要写注释!我曾经因为加了一行 // 这是注释,结果 Broker 启动报错。PLAIN 的 LoginModule 解析器很死板,不支持注释。

4.3.2 修改 server.properties

在 config/server.properties 里加上这些配置:

# 监听器配置,带上 SASL_PLAINTEXT 或 SASL_SSL
listeners=SASL_PLAINTEXT://0.0.0.0:9093

# 安全协议
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=PLAIN

# 启用 SASL
sasl.enabled.mechanisms=PLAIN

# 指定 JAAS 文件路径
# 注意:这个参数要加在 JVM 启动参数里,不是 server.properties
# 在 bin/kafka-server-start.sh 里加:
# export KAFKA_OPTS="-Djava.security.auth.login.config=/path/to/kafka_server_jaas.conf"

嗯,这里有个坑——java.security.auth.login.config 是 JVM 参数,不是 Kafka 配置。我见过有人把它写在 server.properties 里,结果怎么都不生效。

正确的做法是修改启动脚本:

# 在 kafka-server-start.sh 里找到这行
# exec $base_dir/kafka-run-class.sh $EXTRA_ARGS kafka.Kafka "$@"
# 改成:
export KAFKA_OPTS="-Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf"
exec $base_dir/kafka-run-class.sh $EXTRA_ARGS kafka.Kafka "$@"

4.4 客户端配置:生产者与消费者

客户端配置相对简单,但不同客户端写法不一样。咱们分别看 Java 客户端和命令行工具。

4.4.1 Java 客户端配置

生产者和消费者的配置几乎一样,核心就是加认证信息:

Properties props = new Properties();

// 基础配置
props.put("bootstrap.servers", "kafka1:9093,kafka2:9093");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

// SASL 配置
props.put("security.protocol", "SASL_PLAINTEXT");
props.put("sasl.mechanism", "PLAIN");

// JAAS 配置(直接写在代码里,不推荐生产使用)
props.put("sasl.jaas.config",
  "org.apache.kafka.common.security.plain.PlainLoginModule required " +
  "username=\"producer\" password=\"producer-secret\";");

我的建议:生产环境别把密码硬编码在代码里。可以用环境变量或者配置中心动态注入。我曾经接手过一个项目,密码直接写在 Git 仓库里,那叫一个酸爽。

4.4.2 命令行工具配置

用 kafka-console-producer.sh 和 kafka-console-consumer.sh 时,需要创建一个 JAAS 文件给客户端用:

# 创建 client_jaas.conf
KafkaClient {
  org.apache.kafka.common.security.plain.PlainLoginModule required
  username="producer"
  password="producer-secret";
};

然后启动时带上 JVM 参数:

# 生产者
export KAFKA_OPTS="-Djava.security.auth.login.config=/path/to/client_jaas.conf"
kafka-console-producer.sh --broker-list kafka1:9093 --topic test-topic \
  --producer-property security.protocol=SASL_PLAINTEXT \
  --producer-property sasl.mechanism=PLAIN

# 消费者
export KAFKA_OPTS="-Djava.security.auth.login.config=/path/to/client_jaas.conf"
kafka-console-consumer.sh --bootstrap-server kafka1:9093 --topic test-topic \
  --consumer-property security.protocol=SASL_PLAINTEXT \
  --consumer-property sasl.mechanism=PLAIN

4.5 验证与排障

配置完了,怎么验证?我一般这么干:

  1. 启动 Broker,看日志里有没有 Registered broker 0 at path ... with supported SASL mechanisms: PLAIN
  2. 用命令行工具尝试生产和消费
  3. 故意输错密码,看会不会报 Authentication failed

如果连不上,先检查这几个地方:

问题现象 可能原因 排查方法
连接超时 端口不对,或者防火墙没开 telnet 测试端口连通性
Authentication failed 用户名或密码错误 检查 JAAS 文件,注意空格和大小写
No supported SASL mechanism Broker 没启用 PLAIN 检查 sasl.enabled.mechanisms 配置
JAAS file not found JVM 参数没生效 检查启动脚本,确认文件路径