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,结果安全审计直接挂了。
具体流程是这样的:
- 客户端发起连接请求,告诉 Broker "我要用 SASL/PLAIN"
- Broker 回复 "好,把你的凭证拿来"
- 客户端发送用户名 + 密码(明文)
- Broker 拿着凭证去
JAAS配置文件里找匹配项 - 匹配成功 → 认证通过;匹配失败 → 连接断开
核心要点: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 验证与排障
配置完了,怎么验证?我一般这么干:
- 启动 Broker,看日志里有没有
Registered broker 0 at path ... with supported SASL mechanisms: PLAIN - 用命令行工具尝试生产和消费
- 故意输错密码,看会不会报
Authentication failed
如果连不上,先检查这几个地方:
| 问题现象 | 可能原因 | 排查方法 |
|---|---|---|
| 连接超时 | 端口不对,或者防火墙没开 | telnet 测试端口连通性 |
| Authentication failed | 用户名或密码错误 | 检查 JAAS 文件,注意空格和大小写 |
| No supported SASL mechanism | Broker 没启用 PLAIN | 检查 sasl.enabled.mechanisms 配置 |
| JAAS file not found | JVM 参数没生效 | 检查启动脚本,确认文件路径 |