项目

通用

个人资料

操作

模块 mod_auth - 使用认证

描述

认证授权是非常重要的概念。lighttpd 提供了多种认证和授权方法以及后端。您无需全部理解它们。相反,请选择满足您要求的方法。

快速开始

这是一个不太安全的简单配置,但它是实现基本功能并在此基础上改进的起点。创建认证文件并使用以下配置启动 lighttpd。整个站点将需要认证。在浏览器中打开该站点,使用用户名 "agent007" 和密码 "secret" 登录。
echo "agent007:secret" > /tmp/lighttpd-plain.user # 不安全的位置;临时;不安全的密码;请勿在测试环境之外使用

server.modules += ("mod_auth", "mod_authn_file")
auth.backend = "plain" 
auth.backend.plain.userfile = "/tmp/lighttpd-plain.user"  # insecure location; temporary; FIX
auth.require = ( "" => ("method" => "basic", "realm" => "example", "require" => "valid-user") )

HTTP 认证方法

lighttpd mod_auth 原生支持以下认证方法
  • HTTP Basic 认证:RFC 7617 'Basic' HTTP 认证方案
  • HTTP Digest 认证:RFC 7616 HTTP Digest 访问认证

HTTP Basic 认证

HTTP Basic 认证方法通过网络传输用户名和密码(base64 编码)的明文。强烈建议在客户端和服务器之间通过加密通道(HTTPS)使用 HTTP Basic 认证。

通常应优先选择 HTTP Digest 认证而非 HTTP Basic 认证。

HTTP Digest 认证

HTTP Digest 认证方法仅通过网络传输哈希值,这比 HTTP Basic 认证安全得多,但对于历史默认的 MD5 摘要算法来说,其加密强度仍然较弱。(SHA-256 摘要算法更安全)。强烈建议在客户端和服务器之间通过加密通道(HTTPS)使用 HTTP Digest 认证。

通常应优先选择 HTTP Digest 认证而非 HTTP Basic 认证。

HTTP 认证后端

根据 HTTP 认证方法,lighttpd 提供了多种存储用于认证的凭据的方式。某些存储类型,例如存储 SHA-256 摘要,比存储纯文本更安全,但需要更多的设置和维护工作。一些后端在初始设置时需要更多努力,但对于大量用户来说,维护起来更容易。lighttpd 提供了许多选项,因为没有一劳永逸的解决方案,而且本文无法推荐一个特定的后端。话虽如此,如果您熟悉使用数据库并拥有多个用户,请考虑使用 DBI 后端 (mod_authn_dbi)。

对于 HTTP Basic 认证
  • plain
  • htpasswd
  • htdigest
  • dbi (pgsql, mysql, sqlite3 等)
  • ldap
  • gssapi
  • pam
  • sasl
对于 HTTP Digest 认证
  • plain
  • htdigest
  • dbi (pgsql, mysql, sqlite3 等)

plain (mod_authn_file)

一个文件,其中包含用冒号分隔的用户名和明文密码。每个条目以单个换行符终止。
例如:agent007:secret

htpasswd (mod_authn_file)

一个文件,其中包含用冒号分隔的用户名和 crypt() 加密后的密码。每个条目以单个换行符终止。
例如:agent007:XWY5JwrAVBXsQ

您可以使用 Apache 发行版中的 htpasswd 来管理这些文件。htpasswd -h 带有选择不同算法(例如 MD5、SHA1、SHA-256、SHA-512 等)的标志。
$ htpasswd lighttpd.user.htpasswd agent007

htdigest (mod_authn_file)

一个文件,每行包含一个用户身份标识。每行包含用户名、领域和(MD5 或 SHA-256)哈希值,它们之间用冒号分隔。哈希值是连接用户名、领域和密码(之间用冒号分隔)的字符串的校验和,例如:当 user=agent007 realm='download area' pass='secret' 时,哈希值是字符串 agent007:download area:secret 的哈希值。(注意:优先使用 printf 而不是 echo,以避免在字符串中意外地哈希一个换行符。)

您可以使用 Apache 发行版中的 htdigest 来管理 htdigest 文件。
$ htdigest lighttpd.user.htdigest 'download area' agent007

MD5 选项:如果您提供 $user$realm$pass
$ printf "%s:%s:%s\n" "$user" "$realm" "$(printf "%s" "$user:$realm:$pass" | md5sum | awk '{print $1}')"
agent007:download area:8364d0044ef57b3defcfa141e8f77b65

SHA-256 选项:如果您提供 $user$realm$pass
$ printf "%s:%s:%s\n" "$user" "$realm" "$(printf "%s" "$user:$realm:$pass" | sha256sum | awk '{print $1}')"
agent007:download area:a8cad3bc8ff829e27b76aeffc1d722d45c4bcb43876515d56688f5bdd92a829e

如果您选择 SHA-256 哈希,您还应该通过在 auth.require 部分中添加一行 "algorithm" => "SHA-256" 来启用它们。请参阅下面的“配置模板”部分了解示例。

有关其他选项,请参阅本页底部“文件”部分中用户贡献的脚本 htdigest.sh.txt。

为了支持 RFC 7616 HTTP Digest 认证的 userhash 扩展,lighttpd 1.4.62 及更高版本在 htdigest 文件格式的每行末尾添加了一个额外字段:username:realm:digest:userhash。userhash 值是连接用户名和领域(用冒号分隔)的字符串的校验和,例如 "agent007:download area"
$ printf "%s:%s:%s:%s\n" "$user" "$realm" "$(printf "%s" "$user:$realm:$pass" | md5sum | awk '{print $1}')" "$(printf "%s" "$user:$realm" | md5sum | awk '{print $1}')"
agent007:download area:8364d0044ef57b3defcfa141e8f77b65:871f1c6b2a440b5f974bfab721356785
$ printf "%s:%s:%s:%s\n" "$user" "$realm" "$(printf "%s" "$user:$realm:$pass" | sha256sum | awk '{print $1}')" "$(printf "%s" "$user:$realm" | sha256sum | awk '{print $1}')"
agent007:download area:a8cad3bc8ff829e27b76aeffc1d722d45c4bcb43876515d56688f5bdd92a829e:450e917bbf50408bd0dfa149dbcc0a60454d92b26824b7a7fd029777024a8102
如果 "userhash" => "enable" 参数是 auth.require 的一部分(请参阅下面的模板),则 htdigest 文件中必须包含 userhash。

dbi (mod_authn_dbi) (自 lighttpd 1.4.56 起)

建议使用 DBI 后端将用户名、领域以及加密(crypt())或哈希(消息摘要)密码存储到数据库中。此外,也可以存储组。此模块支持 MySQL/MariaDB、Postgres、SQLite3 以及可能支持其他具有 libdbi-drivers 的数据库。它采用了比现已弃用的 mod_authn_mysql 更安全的存储参数。

作为最佳实践,密码存储需要使用盐(或等效物)进行加密或哈希。如果编译时使用 libcrypt,则被动支持 模块化加密格式 (Modular Crypt Format)。如果存储哈希(消息摘要),哈希是 $user:$realm:$pass 组合的消息摘要,并且唯一的 $user:$realm: 组合作为盐。 (例如,参考上面 htdigest 格式,将用户、领域和哈希存储在单独的数据库列中)。使用这种组合,同一个数据库表可以用于 HTTP Basic 认证和 HTTP Digest 认证,并且数据库可以避免在持久存储中出现未加密(纯文本)密码。SHA-256 是推荐的消息摘要算法。虽然 MD5 不安全不推荐,但为了兼容性仍然支持 MD5。许多客户端尚不支持使用 SHA-256 的 HTTP Digest 认证,尽管 lighttpd 支持 "algorithm" => "MD5|SHA-256" 发送多个备选摘要质询,但有些客户端不支持多个质询,或者盲目接受第一个质询。

为了保护数据库中哈希数据的安全,建议使用 SHA-256 或 crypt() 与适当的强算法(非 MD5)。即使在使用 HTTP Basic 认证时,SHA-256 或 crypt()(如果必须,也可以是 MD5)也用于在数据库中存储数据。更好的是,如果与已知支持 SHA-256 的客户端一起使用,则使用带有 SHA-256 的 HTTP Digest 认证。 如果客户端未知并且必须假定只支持 MD5,那么您必须做出选择和权衡。如果认证通过 TLS 进行(https://...),那么使用存储 SHA-256 哈希(或 crypt() 密码)的数据库进行 HTTP Basic 认证,可能比使用 MD5 哈希(弱且不安全)的 HTTP Digest 认证是更好的选择,除非您的客户端正在通过中间人 (MITM) TLS 拦截代理,这将把明文密码暴露给解密 TLS 中的代理。如果使用 http://...(使用 TLS),则 HTTP Digest 认证稍微安全一些,可以混淆客户端否则会以明文形式发送的密码。如果摘要算法是 MD5,请记住安全系数很小,因为对于那些决心嗅探密码并随后(轻易地)从弱 MD5 哈希中破解密码的人来说,MD5 仍然不安全。

将密码插入数据库或生成视图时生成 SHA-256 摘要的 SQL 代码片段示例
MySQL/MariaDB:SHA2(CONCAT(username,':',realm,':',plaintext_password), 256)
PostgreSQL 11:sha256(CONCAT(username,':',realm,':',plaintext_password))
理想情况下,明文密码不应存在于 Web 服务器上,但如果存在于数据库中,则更安全的做法是授予 lighttpd 数据库用户读取包含用户、领域和哈希的受限视图的权限;如果可以避免,则不应授予 lighttpd 数据库用户访问包含明文密码的表的权限。

为了支持 RFC 7616 HTTP Digest 认证 userhash 扩展,lighttpd 1.4.62 及更高版本允许配置 auth.backend.dbi,其中包含一个参数,该参数指定一个 SQL 查询,用于按 userhash 查找条目。auth.backend.dbi 参数必须包含 "sql-userhash" => "...",以便按 userhash 查询并返回两列:摘要和用户名。如果 "userhash" => "enable" 参数是 auth.require 的一部分(请参阅下面的模板),则 userhash 必须从数据库中可用。
将行插入数据库或生成视图时生成 SHA-256 userhash 的 SQL 代码片段示例
MySQL/MariaDB:SHA2(CONCAT(username,':',realm), 256)
PostgreSQL 11:sha256(CONCAT(username,':',realm))

ldap (mod_authn_ldap)

ldap 后端执行以下步骤来认证用户

  1. 初始化 LDAP 连接
  2. 将协议版本设置为 LDAPv3
  3. 如果配置了 StartTLS -> 如果提供了 CA 证书,则配置它
  4. 如果配置了 StartTLS -> 使用 StartTLS 激活 TLS
  5. 如果包含 Bind DN -> 使用 Bind-DN 和 Bind-Password 进行简单绑定
  6. 如果没有 Bind-DN -> 匿名简单绑定
  7. 尝试最多两次对 base-DN 进行 SUBTREE 搜索,并应用过滤器。
  8. 检索与过滤器匹配的用户 DN。
  9. 最后,重新初始化连接(遵循上述步骤),这次使用通过过滤器找到的 DN 和用户提供的密码。

如果所有 9 个步骤都无错误地执行,则用户通过认证。

gssapi (mod_authn_gssapi) (kerberos5) (自 lighttpd 1.4.42 起)

gssapi 后端针对 Kerberos5 基础设施认证用户

mysql (mod_authn_mysql) (自 lighttpd 1.4.42 起)

mysql 后端针对 MySQL/MariaDB 基础设施认证用户

  • 已弃用 请迁移使用 mod_authn_dbi。
  • 注意 mod_authn_dbi 要求数据库存储 "username:realm:password" 的哈希值,以便该值可用于 Basic 认证和 Digest 认证。
    这与 mod_authn_mysql 不同,后者一次只能使用 Basic 认证或 Digest 认证中的一种。这是因为 mod_authn_mysql 期望数据库仅为 Basic 认证存储密码的无盐(安全性较低)哈希,并且在使用 Digest 认证时,期望数据库存储 "username:realm:password" 的哈希。由于 mod_authn_mysql 使用不安全的 MD5 哈希算法,如果数据库被攻破,Basic 认证密码很容易被现成的彩虹表破解。另一方面,mod_authn_dbi 有一个选项可以使用更安全的 SHA256 哈希算法,并且存储的哈希值是组合字符串 "username:realm:password" 的哈希值,它们不像没有盐的 MD5 哈希值那样容易被破解。
  • 从 mod_authn_mysql 迁移到 mod_authn_dbi
    • auth.backend.mysql.* 指令转换为 auth.backend.dbi += (...)(请参阅下面的示例)
    • 如果使用 Basic 认证:将数据库表的密码列转换为存储 "username:realm:password" 的哈希值
    • 如果使用 Digest 认证:无需额外操作;数据库已存储 "username:realm:password" 的哈希值
    • 可选:如果 mod_auth Digest 认证中启用 SHA-256 选项,或者如果修改 SQL 查询以将 SHA-256 哈希值(在数据库中)与 Basic 认证一起使用,则添加带有 SHA-256 哈希值的数据。

pam (mod_authn_pam) (自 lighttpd 1.4.51 起)

PAM 后端针对 PAM 基础设施认证用户,并要求 lighttpd 作为 root 用户运行。不建议使用 mod_authn_pam,除非是特殊用途系统,其中使用 PAM 是为了与现有系统主认证机制集成,例如使用配置了 RADIUS 后端到 PAM 的 PAM。通常,如果用户账户拥有超出 Web 服务所需有限访问的其他权限或访问权限,则 Web 服务不应直接使用系统密码数据库。
auth.backend.pam.opts = ("service" => "http") # (默认)

/etc/pam.d/http (示例)

  auth      sufficient   pam_unix.so nodelay try_first_pass
  auth      requisite    pam_succeed_if.so uid >= 1000 quiet_success
  auth      required     pam_deny.so

  account   required     pam_unix.so
  account   required     pam_access.so accessfile=/etc/security/http.access.conf

要创建 /etc/security/http.access.conf 来定义用户/组访问,请参阅 man pam_accesspam_access

sasl (mod_authn_sasl) (自 lighttpd 1.4.48 起)

SASL 后端针对 SASL 基础设施认证用户

配置模板

设置好后端后,编辑认证配置文件以反映您选择的后端。以下是一个配置模板。

################

## type of backend 
# plain, htpasswd, htdigest (mod_authn_file)
# dbi (mod_authn_dbi)
# ldap (mod_authn_ldap)
# gssapi (mod_authn_gssapi)
# mysql (mod_authn_mysql) (deprecated; use mod_authn_dbi)
# pam (mod_authn_pam)
# sasl (mod_authn_sasl)

################

## for plain, htpasswd, htdigest (mod_authn_file)
server.modules += ( "mod_authn_file" )

## for plain filename of the password storage for plain
auth.backend = "plain" 
auth.backend.plain.userfile = "/path/to/lighttpd-plain.user" 

## for htpasswd
auth.backend = "htpasswd" 
auth.backend.htpasswd.userfile = "/path/to/lighttpd-htpasswd.user" 

## for htdigest
auth.backend = "htdigest" 
auth.backend.htdigest.userfile = "/path/to/lighttpd-htdigest.user" 

################

## for ldap
# the $ in auth.backend.ldap.filter is replaced by the 'username' from the login dialog
# since lighttpd 1.4.46, '?' can be used as placeholder instead of '$', e.g. "(uid=?)" 
# Configure filter to use "samaccountname" instead of "uid" if using Active Directory
server.modules += ( "mod_authn_ldap" )
auth.backend = "ldap" 
auth.backend.ldap.hostname = "localhost" 
auth.backend.ldap.base-dn  = "dc=my-domain,dc=com" 
auth.backend.ldap.filter   = "(uid=$)" 
#auth.backend.ldap.filter = (samaccountname=$)  # Active Directory
# if enabled, startTLS needs a valid (base64-encoded) CA 
# certificate unless the certificate has been stored
# in a c_hashed directory and referenced in ldap.conf
auth.backend.ldap.starttls   = "enable" 
auth.backend.ldap.ca-file   = "/etc/CAcertificate.pem" 
# If you need to use a custom bind to access the server
auth.backend.ldap.bind-dn  = "uid=admin,dc=my-domain,dc=com" 
auth.backend.ldap.bind-pw  = "mysecret" 
# If you want to allow empty passwords
# "disable" for requiring passwords, "enable" for allowing empty passwords
auth.backend.ldap.allow-empty-pw = "disable" 
# LDAP group (https://redmine.lighttpd.ac.cn/issues/1817)
#auth.backend.ldap.groupmember = "mygroup" 
# LDAP network timeout in microseconds (2000000 us = 2 sec) (OpenLDAP-specific) (since 1.4.56)
#auth.backend.ldap.timeout = "2000000" 

################

## for gssapi
server.modules += ( "mod_authn_gssapi" )
auth.backend = "gssapi" 
auth.backend.gssapi.keytab = "/path/to/lighttpd.keytab" 
auth.backend.gssapi.principal = "myhost" 
auth.backend.gssapi.store-creds = "enable"   # default: "enable" ("disable" recommended unless storing creds is needed)

################

# DBI
server.modules += ( "mod_authn_dbi" )
auth.backend = "dbi" 

# (with PostgreSQL)
#auth.backend.dbi += (
#      # required
#      "sql"           => "SELECT digest FROM users WHERE user='?' AND realm='?'",
#      "sql-userhash"  => "SELECT digest,user FROM users WHERE userhash='?'",
#      "dbtype"        => "pgsql",       # DBI database driver string name
#      "dbname"        => "lighttpd",
#      # optional
#      "username"      => "lighttpd",    # (some dbtype do not require username, e.g. sqlite)
#      "password"      => "",            # (default: empty)
#      "socket"        => "/path/sock",  # (default: dbtype default)
#      "host"          => "localhost",   # (if set, overrides "socket")
#      "port"          => 5432,          # (default: dbtype default)
#      "encoding"      => "UTF-8",       # (default: dbtype default)
#)

# (with SQLite3)
# auth.backend.dbi += (
#   "sql" => "SELECT digest FROM users WHERE user='?' AND realm='?'" 
#   "sql-userhash" => "SELECT digest,user FROM users WHERE userhash='?'" 
#   "dbtype" => "sqlite3",
#   "dbname" => "auth.db",
#   "sqlite3_dbdir" => "/path/to/sqlite/dbs/" 
# )

# feature: mod_authn_dbi will substitute username, then realm, then algorithm ("SHA-256" or "MD5")
#   for the first, second (optional), and third (optional) '?' in the SQL statement.
#   "SELECT digest FROM users WHERE user='?' AND realm='?' and algorithm='?'" 
# feature: since mod_authn_dbi permits you to specify the SQL statement, you may also
#   use the SQL query to combine authentication and authorization using groups in the
#   database, if you so choose. 
#   "SELECT digest FROM users WHERE user='?' AND realm='?' and group='administrators_group'" 

################

## for mysql (Deprecated: please migrate to use mod_authn_dbi)
server.modules += ( "mod_authn_mysql" )    # server.modules += ( "mod_authn_dbi" )
auth.backend = "mysql"                     # auth.backend = "dbi" 
                                           # auth.backend.dbi += (
                                           #   "dbtype"   => "mysql", # required
#auth.backend.mysql.host = ""              #   "host"     => "..."    # optional
#auth.backend.mysql.user = ""              #   "username" => "..."    # optional
#auth.backend.mysql.pass = ""              #   "password" => "..."    # optional
#auth.backend.mysql.db = ""                #   "dbname"   => "..."    # required
#auth.backend.mysql.port = ""              #   "port"     => 3306     # optional
#auth.backend.mysql.socket = ""            #   "socket"   => "..."    # optional
                                           #   "sql"      =>          # required
                                           #                 "SELECT password FROM users WHERE user='?' AND realm='?'" 
                                           # )
auth.backend.mysql.users_table = "users"   #                                      #users
#auth.backend.mysql.col_user = "user"      #                                                  #user
#auth.backend.mysql.col_pass = "password"  #                        #password
#auth.backend.mysql.col_realm = "realm"    #                                                               #realm
# defaults above result in query: SELECT password FROM users WHERE user='%s' AND realm='%s'

################

## for pam
server.modules += ( "mod_authn_pam" )
auth.backend = "pam" 
#auth.backend.pam.opts = ( "service" => "http" )  # default "http" 

################

## for sasl
server.modules += ( "mod_authn_sasl" )
auth.backend = "sasl" 
#auth.backend.sasl.opts = ( "service"        => "http",      # default "http" 
#                           "fqdn"           => "hostname",  # default current host
#                           "pwcheck_method" => "saslauthd", # default "saslauthd", else one of "saslauthd","auxprop","sasldb" 
#                           "sasldb_path"    => "path-to-db" # if needed
#                         )

################

# check REMOTE_USER (if set) against require rules prior to applying auth.backend
# REMOTE_USER might be set by another module, e.g. mod_openssl client cert verification
# and REMOTE_USER configured with ssl.verifyclient.username)
# (since lighttpd 1.4.46)
#auth.extern-authn = "enable" 

################
################

## restrictions
# set restrictions:
#
# auth.require =
# ( <url-path-prefix> =>
#   ( "method" => "digest"/"basic",
#     "realm" => <realm>,
#     "require" => "user=<username>" )
# )
#
# <url-path-prefix> is url-path prefix to match, e.g. "/" 
#   First match is used; requirements are not combined.
#   If nested paths have different auth requirements, then list
#   from longest to shortest, e.g. "/a/b/" before "/a/" 
#
# <algorithm> is the digest algorithm to use with "method" => "digest", as well as htdigest files.
#   The default digest algorithm MD5 is no longer considered secure.
#   lighttpd can be configured to use SHA-256 (since lighttpd 1.4.54)
#   If not specified, MD5 is used for backwards compatibility.
#   The examples below use "algorithm" => "SHA-256", though some
#   clients do not support SHA-256 digests.  lighttpd could provide
#   both challenges using "SHA-256|MD5", but some clients do not support
#   multiple digest challenges, so the default remains
#   "algorithm" => "MD5" if not otherwise specified.
#
# "algorithm" => "SHA-256" # (optional) (since 1.4.54)
#
# RFC 7616 HTTP Digest auth userhash extension (since 1.4.62)
#   supported with mod_authn_file htdigest
#     and htdigest data file must have userhash field
#   supported with mod_authn_dbi with "sql-userhash" 
#     and database must have userhash column
#   Do not "enable" unless auth backend is configured to support userhash
#   as enabling this flag causes lighttpd to request userhash from client.
#
# "userhash" => "enable"   # (optional) (since 1.4.62)
#
# <realm> is a string to display in the dialog 
#         presented to the user and is also used for the 
#         digest-algorithm and has to match the realm in the 
#         htdigest file (if used)
#
# "require" => "valid-user" will authorize any authenticated user
#
# "nonce-secret" => "my-extra-secret" # (optional) (since lighttpd 1.4.56)
#         If "nonce-secret" is set, the secret is used to validate that
#         the server generated the nonce used in HTTP Digest Auth
#         (i.e. to detect a client attack spoofing nonces)
#         Please replace "my-extra-secret" with a more complex secret.
#

server.modules += ( "mod_auth" )

auth.require = ( "/download/" =>
                 (
                 # method must be either basic or digest
                   "method"    => "digest",
                   "algorithm" => "SHA-256",
                   "realm"     => "download archiv",
                   "require"   => "user=agent007|user=agent008" 
                 ),
                 "/server-info" =>
                 (
                 # limit access to server information
                   "method"    => "digest",
                   "algorithm" => "SHA-256",
                   "realm"     => "download archiv",
                   "require"   => "valid-user" 
                 )
                 "/protected-folder/" =>
                 (
                 # 
                   "method"    => "digest",
                   "algorithm" => "SHA-256",
                   "realm"     => "download archiv",
                   "require"   => "valid-user" 
                 )
               )

# Or, using regular expressions:
$HTTP["url"] =~ "^/download|^/server-info" {
  auth.require = ( "" =>
                   (
                     "method"    => "digest",
                     "algorithm" => "SHA-256",
                     "realm"     => "download archiv",
                     "require"   => "user=agent007|user=agent008" 
                   )
                 )
}

# Or, if *only* using certificate based authentication along with mod_openssl configured to require client certificates
#  # client side authentification       
#  ssl.verifyclient.activate = "enable" 
#  ssl.verifyclient.enforce = "enable" 
#  # this line instructs client cert CN value to be extracted
#  # for use in require user=agent007... in auth.require
#  ssl.verifyclient.username = "SSL_CLIENT_S_DN_CN" 
auth.require = ( "" =>
                 (
                   "method"  => "extern",
                   "realm"   => "certificate",
                   "require" => "user=agent007|user=agent008" 
                 )
               )

缓存

auth.cache = ("max-age" => "600") (默认:不活动;无缓存) (自 lighttpd 1.4.56 起)
在内存中缓存密码/摘要以减少后端负载。max-age 以秒为单位。每 8 秒检查一次缓存是否过期,因此实际缓存时间可能比配置的 max-age 长最多 8 秒。

警告

mod_rewrite 规则 (url.rewrite*,而非 url.rewrite-if-not-file) 总是先于其他所有操作执行,并且请求会重新启动。因此您的 mod_auth 配置必须与重写后的 URL 匹配!

当 lighttpd 使用加密库(TLS 模块或 Nettle 加密库)构建时,lighttpd 支持 SHA-256 摘要,因为 lighttpd 从这些库获取 SHA-256 摘要函数。

lighttpd 和 Firefox 浏览器都支持 SHA-256 摘要,但大多数其他客户端对 SHA-256 摘要的支持不佳。
https://redmine.lighttpd.ac.cn/boards/2/topics/8955
https://redmine.lighttpd.ac.cn/boards/2/topics/8903

Firefox 93.0 支持 RFC 7616 HTTP Digest 访问认证的 SHA-256
(Firefox 93.0 正式发布:2021 年 10 月 5 日)

Chrome 中的开放问题
https://bugs.chromium.org/p/chromium/issues/detail?id=1160478 "符合 rfc7616 的 HTTP Digest 访问认证的 SHA-256"

Opera 浏览器过去支持 SHA-256 摘要,直到它转换为基于 Chromium。

Chrome 117.0.5915.0 支持 RFC 7616 HTTP Digest 访问认证的 SHA-256
(Chrome 117 发布到 Chrome 稳定版渠道:2023 年 9 月)
https://bugs.chromium.org/p/chromium/issues/detail?id=1160478

限制

自 lighttpd 1.4.41 起,摘要方法的实现符合 RFC7616 (#1844))
摘自 https://www.rfc-editor.org/rfc/rfc7616.txt 第 5.13 节
总之,任何符合规范的实现都将是
根据密码学标准相对较弱,但任何符合规范的实现
都将远远优于 Basic 认证。

即便如此,仍然存在局限性,并且可以进行改进。

  • 摘要方法的实现无法阻止某些类型的重放攻击。(在 lighttpd 1.4.56 中已改进 #2976
  • Digest 算法 "md5-sess" 在 lighttpd 中未正确实现,可能永远不会实现,因此不建议使用它。(#806)Apache 的 mod_auth_digest 也未实现算法 "md5-sess"。

现代 lighttpd 中已修复的历史限制或有替代方案的限制

  • 当与 mod_fastcgi 一起加载时,mod_auth 必须mod_fastcgi 之前加载。否则用户在登录时会遇到长时间延迟,并且系统管理员可能由于缺乏有意义的错误消息而无法找出问题来源。
    • lighttpd 1.4.62 中发出了警告跟踪
  • 截至 1.4.19 版本,require 指令中的 group 字段尚未实现。因此,auth.backend.plain.groupfile 目前无法使用。
    • 自 lighttpd 1.4.46 起支持 LDAP 组 (#1817))
    • 如果用户在数据库中访问的 SQL 查询或视图中实现了 mod_authn_dbi 组支持,则可用
  • LDAP 认证只允许不包含标点符号的字母数字 UID。即:john.doe 将显示为 "ldap: 用户名中包含无效字符 (只允许 a-zA-Z0-9):john.doe"
    • 此问题似乎已在 r2526 中解决。请参阅问题 #1941)(在 lighttpd 1.4.46 中已修复

另请参阅

更新者 gstrauss 2 个月前 · 92 个修订版