凭证和密码
概述
本指南涵盖了与内部身份验证后端所使用的凭证和密码相关的各种主题。如果使用了其他身份验证后端,本指南中的大部分内容将不再适用。
RabbitMQ 支持多种身份验证机制。其中一些使用用户名/密码对。这些凭证对随后会被传递给执行身份验证的身份验证后端。其中一种被称为内部或内置(internal/built-in)的后端,使用 RabbitMQ 内部数据存储来存储用户凭证。当使用 rabbitmqctl 添加新用户时,用户的密码会与盐值(salt)合并并进行哈希处理。
RabbitMQ 可以配置为使用不同的密码哈希函数
- SHA-256
- SHA-512
默认使用 SHA-256。更多算法可通过插件提供。
配置所使用的算法
可以通过 RabbitMQ 配置文件更改所使用的算法,例如更改为使用 SHA-512。
password_hashing_module = rabbit_password_hashing_sha512
开箱即用,提供了以下哈希模块
rabbit_password_hashing_sha256(默认)rabbit_password_hashing_sha512rabbit_password_hashing_md5(用于向后兼容)
更新后的哈希算法将应用于新创建的用户,或当使用 rabbitmqctl 更改密码时生效。
凭证验证
RabbitMQ 支持凭证验证器。验证器仅对内部身份验证后端生效,并在添加新用户或更改现有用户密码时触发。
验证器是实现了验证功能的模块。要使用验证器,必须在配置文件中指定它及其附加设置。
开箱即用提供了三种凭证验证器
rabbit_credential_validator_accept_everything:无条件接受所有值。出于向后兼容性考虑,此验证器为默认使用。rabbit_credential_validator_min_password_length:验证密码长度。rabbit_credential_validator_password_regexp:验证密码是否匹配正则表达式(有一些限制,见下文)。
以下示例展示了如何使用 rabbit_credential_validator_min_password_length
credential_validator.validation_backend = rabbit_credential_validator_min_password_length
credential_validator.min_length = 30
以下示例展示了如何使用 rabbit_credential_validator_password_regexp
credential_validator.validation_backend = rabbit_credential_validator_password_regexp
credential_validator.regexp = ^[a-bA-Z0-9$]{20,100}
凭证验证器限制
凭证验证器存在一些限制,这些限制既与配置文件语法有关,也与在命令行指定凭证时 Shell 对某些字符的解释有关。
新样式的配置格式使用 # 作为注释字符。这意味着验证规则的正则表达式值中不能包含 #。配置文件解析器还会剥离值中的前导和尾随空格。
另请注意,当在管理用户的 CLI 工具命令中使用密码时,必须考虑 Shell 对某些字符的转义处理。
自定义凭证验证器
每个凭证验证器都是一个实现单一函数行为(behavior)的模块,即 rabbit_credential_validator。因此,插件可以提供更多的实现。
凭证验证器还可以验证用户名或应用任何其他逻辑(例如,确保提供的用户名和密码不相同)。
无密码用户
内部身份验证后端允许存在没有密码或密码为空的用户(前提是凭证验证器也允许)。此类用户仅适用于不需要密码的身份验证机制,例如使用 x509 证书进行身份验证。
要创建无密码用户,请使用任何通过验证的密码创建一个用户,然后使用 rabbitmqctl 的 clear_password 命令清除该密码。
rabbitmqctl add_user passwordless-user "pa$$wordless"
rabbitmqctl clear_password passwordless-user
# don't forget to grant the user virtual host access permissions using set_permissions
# ...
使用空密码的身份验证尝试将被内部身份验证后端无条件拒绝,并在服务器日志中显示一条明显的错误消息。使用 x509 证书进行身份验证或使用外部服务(如 LDAP)进行身份验证的连接可以使用空密码。
使用 TLS (x509) 证书进行身份验证
可以通过 x509 证书验证连接并完全避免使用密码。身份验证过程随后将依赖于 TLS 对等证书链验证。
步骤如下:
- 创建无密码用户(见上文)
- 启用 rabbitmq-auth-mechanism-ssl 插件
- 按照该插件的配置说明操作
- 将客户端连接配置为使用 TLS 和
EXTERNAL身份验证机制 - 将客户端连接配置为提供证书/密钥对和 CA 证书(或证书链)。证书链将由服务器验证,因此其中的至少一个证书必须被目标节点所信任。
计算密码哈希值
有时需要计算用户的密码哈希值以便通过 HTTP API 进行更新,或生成用于导入的定义文件。
通过 rabbitmqctl 哈希
rabbitmqctl hash_password foobarbaz
# Outputs
# Will hash password foobarbaz
# 27cx5+wEi8R8uwTeTr3hk5azuV3yYxxAtwPPhCyrbdsxVhqq
通过 rabbitmqadmin 哈希
rabbitmqadmin passwords salt_and_hash foobarbaz
# Outputs
# ┌───────────────┬──────────────────────────────────────────────────┐
# │ Result │
# ├───────────────┼──────────────────────────────────────────────────┤
# │ key │ value │
# ├───────────────┼──────────────────────────────────────────────────┤
# │ password hash │ 5ZbXJB3OWQlCzUNybwJ/XcL6ZqJA9zNQvXlwYnWQikQSP3lz │
# └───────────────┴──────────────────────────────────────────────────┘
通过 HTTP API 哈希
curl -4su guest:guest -X GET localhost:15672/api/auth/hash_password/foobarbaz
# Output:
# {"ok":"TBybOvomyVw6BqBU/fHCEpVhDO7fLdQ4kxZDUpt6hagCxV8I"}
算法如下:
- 生成一个 32 位的随机盐值。在本例中,我们将使用
908D C60A。当 RabbitMQ 创建或更新用户时,会自动生成随机盐值。 - 将生成的盐值置于所需密码的 UTF-8 表示形式之前。如果密码是
test12,这一步的中间结果将是908D C60A 7465 7374 3132 - 取哈希值(本例假设使用默认哈希函数,SHA-256):
A5B9 24B3 096B 8897 D65A 3B5F 80FA 5DB62 A94 B831 22CD F4F8 FEAD 10D5 15D8 F391 - 再次在前面加上盐值:
908D C60A A5B9 24B3 096B 8897 D65A 3B5F 80FA 5DB62 A94 B831 22CD F4F8 FEAD 10D5 15D8 F391 - 将该值转换为 base64 编码:
kI3GCqW5JLMJa4iX1lo7X4D6XbYqlLgxIs30+P6tENUV2POR - 在 HTTP API 请求和生成的定义文件中,使用最终的 base64 编码值作为
password_hash的值。