VirtualBox

Trac 和 mod_wsgi

mod_wsgi 是一个 Apache 模块,用于在 Apache Web 服务器上直接运行 WSGI 兼容的 Python 应用程序。mod_wsgi 适配器完全用 C 语言编写,提供了非常好的性能。

概述

  1. trac.wsgi 脚本
    1. 一个非常基础的脚本
    2. 一个更精细的脚本
  2. 将请求映射到脚本
  3. 配置身份验证
    1. 使用基本认证
    2. 使用摘要认证
    3. 使用 LDAP 认证
    4. 使用 SSPI 认证
    5. 使用 CA SiteMinder 认证
    6. 示例:使用 Apache/mod_wsgi 和基本认证,Trac 位于虚拟主机根目录
  4. 故障排除
    1. 使用最新版本
    2. 使 Trac 很好地与 SSPI 和 'Require Group' 配合工作
    3. Trac 与 PostgreSQL
    4. 其他资源

trac.wsgi 脚本

Trac 可以借助应用程序脚本在 mod_wsgi 上运行,该脚本是一个以 .wsgi 扩展名保存的 Python 文件。

可以使用 trac-admin <env> deploy <dir> 命令创建此文件的健壮且通用版本,该命令会自动替换所需的路径,请参阅 TracInstall#cgi-bin。该脚本足以满足大多数安装,不需要更多信息的用户可以继续配置 Apache

如果您将 Trac 用于多个项目,可以在 trac.wsgi 中指定它们的共同父目录

def application(environ, start_request):
    # Add this when you have multiple projects
    environ.setdefault('trac.env_parent_dir', '/usr/share/trac/projects')
    ..

位于 trac.env_parent_dir 中但不是环境目录的目录将在项目索引页上显示错误消息。这些目录可以通过将它们列在 trac.env_parent_dir 中名为 .tracignore 的文件中来排除。Unix shell 风格的通配符模式可以在以换行符分隔的目录列表中使用。

一个非常基础的脚本

最简单的形式,脚本可以是

import os

os.environ['TRAC_ENV'] = '/usr/local/trac/mysite'
os.environ['PYTHON_EGG_CACHE'] = '/usr/local/trac/mysite/eggs'

import trac.web.main
application = trac.web.main.dispatch_request

TRAC_ENV 变量自然应该是您的 Trac 环境目录,而 PYTHON_EGG_CACHE 应该是一个 Python 可以临时提取 Python egg 的目录。如果您的目录中有多个 Trac 环境,您也可以使用 TRAC_ENV_PARENT_DIR 而不是 TRAC_ENV

在 Windows 上

  • 如果在用户会话下运行,Python Egg 缓存可以在 %AppData%\Roaming 中找到,例如
    os.environ['PYTHON_EGG_CACHE'] = r'C:\Users\Administrator\AppData\Roaming\Python-Eggs'
    
  • 如果在 Windows 服务下运行,您应该为 Python Egg 缓存创建一个目录
    os.environ['PYTHON_EGG_CACHE'] = r'C:\Trac-Python-Eggs'
    

一个更精细的脚本

如果您使用多个 .wsgi 文件(例如每个 Trac 环境一个),则不得使用 os.environ['TRAC_ENV'] 来设置 Trac 环境的路径。使用此方法可能会导致 Trac 提供另一个 Trac 环境的内容,因为该变量可能被之前查看的 Trac 环境的路径填充。

要解决此问题,请改用以下 .wsgi 文件

import os

os.environ['PYTHON_EGG_CACHE'] = '/usr/local/trac/mysite/eggs'

import trac.web.main
def application(environ, start_response):
  environ['trac.env_path'] = '/usr/local/trac/mysite'
  return trac.web.main.dispatch_request(environ, start_response)

为了清晰起见,您应该给这个文件一个 .wsgi 扩展名。您可能应该将该文件放在自己的目录中,因为它将暴露给 Apache。

如果您已将 Trac 和 Python eggs 安装在与标准路径不同的路径中,则应通过在 wsgi 脚本顶部添加以下代码来添加该路径

import site
site.addsitedir('/usr/local/trac/lib/python2.4/site-packages')

根据您安装 Trac 库的路径进行更改。

将请求映射到脚本

准备好 .wsgi 脚本后,将以下内容添加到您的 Apache 配置文件(通常是 httpd.conf)中

WSGIScriptAlias /trac /usr/local/trac/mysite/apache/mysite.wsgi

<Directory /usr/local/trac/mysite/apache>
    WSGIApplicationGroup %{GLOBAL}
    # For Apache 2.2
    <IfModule !mod_authz_core.c>
        Order deny,allow
        Allow from all
    </IfModule>
    # For Apache 2.4
    <IfModule mod_authz_core.c>
        Require all granted
    </IfModule>
</Directory>

这里,脚本位于 Trac 环境的一个子目录中。

如果您遵循了生成 Trac cgi-bin 目录的说明,您的 Apache 配置文件应如下所示

WSGIScriptAlias /trac /usr/share/trac/cgi-bin/trac.wsgi

<Directory /usr/share/trac/cgi-bin>
    WSGIApplicationGroup %{GLOBAL}
    # For Apache 2.2
    <IfModule !mod_authz_core.c>
        Order deny,allow
        Allow from all
    </IfModule>
    # For Apache 2.4
    <IfModule mod_authz_core.c>
        Require all granted
    </IfModule>
</Directory>

为了让 Apache 运行脚本,脚本所在目录的访问权限已对 Apache 完全开放。此外,WSGIApplicationGroup 指令确保 Trac 始终在 mod_wsgi 创建的第一个 Python 解释器中运行。这是必要的,因为 Trac 使用的 Subversion Python 绑定在其他子解释器中并非总能正常工作,并可能导致请求挂起或 Apache 崩溃。添加此配置后,重新启动 Apache,然后它应该可以工作了。

为了测试 Apache、mod_wsgi 和 Python 本身(即不涉及 Trac 和依赖项)的设置,可以使用这个简单的 wsgi 应用程序来确保请求得到服务(作为 .wsgi 脚本中唯一的内容使用)

def application(environ, start_response):
        start_response('200 OK',[('Content-type','text/html')])
        return ['<html><body>Hello World!</body></html>']

有关使用 mod_wsgi 特定的指令的更多信息,请参阅 mod_wsgi 的维基以及更具体的 IntegrationWithTrac 页面。

配置身份验证

以下各节介绍了设置认证的不同方法。另请参阅 Apache 指南中的认证、授权和访问控制

使用基本认证

使用 Apache 启用认证最简单的方法是创建密码文件。使用 htpasswd 程序如下:

$ htpasswd -c /somewhere/trac.htpasswd admin
New password: <type password>
Re-type new password: <type password again>
Adding password for user admin

创建第一个用户后,您不再需要“-c”选项

$ htpasswd /somewhere/trac.htpasswd john
New password: <type password>
Re-type new password: <type password again>
Adding password for user john

有关完整文档,请参阅 htpasswd 的手册页。

创建用户后,您可以使用TracPermissions设置他们的权限。

现在,您需要在 Apache 配置中启用对密码文件的认证

<Location "/trac/login">
  AuthType Basic
  AuthName "Trac"
  AuthUserFile /somewhere/trac.htpasswd
  Require valid-user
</Location>

如果您托管多个项目,可以使用相同的密码文件对所有项目进行认证

<LocationMatch "/trac/[^/]+/login">
  AuthType Basic
  AuthName "Trac"
  AuthUserFile /somewhere/trac.htpasswd
  Require valid-user
</LocationMatch>

请注意,不需要存在名为“login”的文件或目录。另请参阅mod_auth_basic 文档。

使用摘要认证

为了更好的安全性,建议您要么启用 SSL,要么至少使用“摘要”认证方案而不是“基本”认证。

您必须使用 htdigest 命令而不是 htpasswd 来创建您的 .htpasswd 文件,如下所示

$ htdigest -c /somewhere/trac.htpasswd trac admin

上面提到的“trac”参数是“realm”,需要Apache配置中 AuthName 指令中重复使用

<Location "/trac/login">
  AuthType Digest
  AuthName "trac"
  AuthDigestDomain /trac
  AuthUserFile /somewhere/trac.htpasswd
  Require valid-user
</Location>

对于多个环境,您可以使用与前述方法相同的 LocationMatch

注意Location 不能在 .htaccess 文件中使用,而必须存在于主 httpd.conf 文件中。如果您在共享服务器上,因此将无法提供这种级别的粒度。

别忘了激活 mod_auth_digest。例如,在 Debian 4.0r1 (etch) 系统上

  LoadModule auth_digest_module /usr/lib/apache2/modules/mod_auth_digest.so

另请参阅mod_auth_digest 文档。

使用 LDAP 认证

Apache 中 mod_ldap 认证的配置更复杂(httpd 2.2+ 和 OpenLDAP: slapd 2.3.19)。

  1. 您需要在 Apache httpd.conf 中加载以下模块
      LoadModule ldap_module modules/mod_ldap.so
      LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
    
  2. 您的 httpd.conf 也需要看起来像这样
    <Location /trac/>
      # (if you're using it, mod_python specific settings go here)
      Order deny,allow
      Deny from all
      Allow from 192.168.11.0/24
      AuthType Basic
      AuthName "Trac"
      AuthBasicProvider "ldap"
      AuthLDAPURL "ldap://127.0.0.1/dc=example,dc=co,dc=ke?uid?sub?(objectClass=inetOrgPerson)"
      authzldapauthoritative Off
      Require valid-user
    </Location>
    
  3. 您可以使用 LDAP 接口作为对 Microsoft Active Directory 进行认证的方式。使用以下内容作为您的 LDAP URL
      AuthLDAPURL "ldap://directory.example.com:3268/DC=example,DC=com?sAMAccountName?sub?(objectClass=user)"
    
    您还需要提供一个 Apache 用于检查凭据的账户。由于此密码将在配置中以纯文本形式列出,因此您需要专门为此任务使用一个账户
      AuthLDAPBindDN ldap-auth-user@example.com
      AuthLDAPBindPassword "password"
    
    整个部分看起来像这样
    <Location /trac/>
      # (if you're using it, mod_python specific settings go here)
      Order deny,allow
      Deny from all
      Allow from 192.168.11.0/24
      AuthType Basic
      AuthName "Trac"
      AuthBasicProvider "ldap"
      AuthLDAPURL "ldap://adserver.company.com:3268/DC=company,DC=com?sAMAccountName?sub?(objectClass=user)"
      AuthLDAPBindDN       ldap-auth-user@company.com
      AuthLDAPBindPassword "the_password"
      authzldapauthoritative Off
      # require valid-user
      Require ldap-group CN=Trac Users,CN=Users,DC=company,DC=com
    </Location>
    

注意 1:这是 LDAP 搜索将绕过多个 OU 的情况,连接到 AD 的全局目录服务器部分。请注意端口是 3268,而不是正常的 LDAP 389。GCS 本质上是一个“扁平化”的树,允许在不知道用户属于哪个 OU 的情况下搜索用户。

注意 2:您还可以要求用户是某个 LDAP 组成员,而不仅仅是拥有有效的登录凭据

  Require ldap-group CN=Trac Users,CN=Users,DC=example,DC=com

另请参阅

使用 SSPI 认证

如果您在 Windows 上使用 Apache,可以使用 mod_auth_sspi 提供单点登录。从 SourceForge mod-auth-sspi 项目下载模块,然后将以下内容添加到您的 VirtualHost 中

<Location /trac/login>
  AuthType SSPI
  AuthName "Trac Login"
  SSPIAuth On
  SSPIAuthoritative On
  SSPIDomain MyLocalDomain
  SSPIOfferBasic On
  SSPIOmitDomain Off
  SSPIBasicPreferred On
  Require valid-user
</Location>

使用上述方法,Trac 中的用户名将是 DOMAIN\username 的形式,因此您可能需要重新添加权限等。如果您不希望域名成为用户名的一部分,请改为设置 SSPIOmitDomain On

SSPI 认证的一些常见问题:#1055#1168#3338

另请参阅TracOnWindows/Advanced

使用 CA SiteMinder 认证

设置 CA SiteMinder 以保护您的 Trac 登录 URL,例如 /trac/login。此外,请确保策略设置为包含 HTTP_REMOTE_USER 变量。如果您的站点允许,您可以在 LocalConfig.conf 中进行设置

RemoteUserVar="WHATEVER_IT_SHOULD_BE"
SetRemoteUser="YES"

具体变量取决于站点。请咨询您的站点管理员。如果您的站点出于安全原因不允许使用 LocalConfig.conf,请让您的站点管理员在服务器上设置策略以设置 REMOTE_USER。

另请在代理配置中添加一个 LogOffUri 参数,例如 /trac/logout

然后修改使用 trac-admin <env> deploy <dir> 生成的 trac.wsgi 脚本,添加以下行,它们将提取 HTTP_REMOTE_USER 变量并将其设置为 REMOTE_USER

def application(environ, start_request):
    # Set authenticated username on CA SiteMinder to REMOTE_USER variable
    # strip() is used to remove any spaces on the end of the string
    if 'HTTP_SM_USER' in environ:
        environ['REMOTE_USER'] = environ['HTTP_REMOTE_USER'].strip()
    ...

您不需要任何 Apache “Location” 指令。

示例:使用 Apache/mod_wsgi 和基本认证,Trac 位于虚拟主机根目录

根据上面链接的 mod_wsgi 文档,这是一个 Apache 配置示例,它

  • 从虚拟主机子域名提供 Trac 实例
  • 使用 Apache 基本认证进行 Trac 认证。

如果您想让 Trac 从例如 http://trac.my-proj.my-site.org 提供服务,然后从例如 /home/trac-for-my-proj 文件夹,如果您使用了命令 trac-admin the-env initenv 创建了 the-env 文件夹,并且您使用了 trac-admin the-env deploy the-deploy 创建了 the-deploy 文件夹,那么首先

创建 htpasswd 文件

cd /home/trac-for-my-proj/the-env
htpasswd -c htpasswd firstuser
### and add more users to it as needed:
htpasswd htpasswd seconduser

出于安全原因,请将文件保存在文档根目录上方。

在 Ubuntu 上创建此文件,例如 /etc/apache2/sites-enabled/trac.my-proj.my-site.org.conf,内容如下

<Directory /home/trac-for-my-proj/the-deploy/cgi-bin/trac.wsgi>
  WSGIApplicationGroup %{GLOBAL}
  Order deny,allow
  Allow from all
</Directory>

<VirtualHost *:80>
  ServerName trac.my-proj.my-site.org
  DocumentRoot /home/trac-for-my-proj/the-env/htdocs/
  WSGIScriptAlias / /home/trac-for-my-proj/the-deploy/cgi-bin/trac.wsgi
  <Location '/'>
    AuthType Basic
    AuthName "Trac"
    AuthUserFile /home/trac-for-my-proj/the-env/htpasswd
    Require valid-user
  </Location>
</VirtualHost>

为了使子域名正常工作,您可能还需要修改 /etc/hosts 并将 A 记录添加到您的主机的 DNS 中。

故障排除

使用最新版本

请使用 mod_wsgi 的 1.6、2.4 或更高版本。2.X 分支中 2.4 之前的版本在某些使用 WSGI 文件包装器扩展的 Apache 配置中存在问题。Trac 中使用此扩展来提供附件和静态媒体文件,例如样式表。如果您受到此问题的影响,附件将显示为空,并且 HTML 页面的格式可能由于样式表文件未正确加载而无法正常工作。另一个常见症状是二进制附件下载被截断。请参阅 mod_wsgi 缺陷报告 #100#132

注意:在我的系统上(Apache 2.2.11 和 Trac 0.11.2.1),使用 mod_wsgi 2.5 和 Python 2.6.1 导致了内部服务器错误。升级到 Python 2.6.2(如此处建议)解决了我的问题
-- Graham Shanks

如果您计划在 Windows 上以嵌入模式或在 Linux 上使用 MPM worker 模式使用 mod_wsgi,那么您将需要 3.4 或更高版本。有关详细信息,请参阅#10675

使 Trac 很好地与 SSPI 和 'Require Group' 配合工作

如果您已在 Apache、Win32 上设置 Trac 并配置了 SSPI,但您的 Apache 配置中添加了 'Require group' 选项,那么 SSPIOmitDomain 选项可能无法正常工作。如果它不工作,您的 Trac 用户名可能看起来像 'DOMAIN\user' 而不是 'user'。

这个 WSGI 脚本修复了这个问题

import os
import trac.web.main

os.environ['TRAC_ENV'] = '/usr/local/trac/mysite'
os.environ['PYTHON_EGG_CACHE'] = '/usr/local/trac/mysite/eggs'

def application(environ, start_response):
    if "\\" in environ['REMOTE_USER']:
        environ['REMOTE_USER'] = environ['REMOTE_USER'].split("\\", 1)[1]
    return trac.web.main.dispatch_request(environ, start_response)

Trac 与 PostgreSQL

当将 mod_wsgi 适配器与多个 Trac 实例以及 PostgreSQL(或 MySQL?)作为数据库一起使用时,服务器可能会创建大量的打开数据库连接,从而导致大量的 PostgreSQL 进程。

一个有点粗暴的解决方法是在 Trac 中禁用连接池。这通过在 PostgreSQLConnection 类的 trac.db.postgres_backend 中设置 poolable = False 来实现。

但没有必要编辑 Trac 的源代码。trac.wsgi 中的以下行也将起作用

import trac.db.postgres_backend
trac.db.postgres_backend.PostgreSQLConnection.poolable = False

import trac.db.mysql_backend
trac.db.mysql_backend.MySQLConnection.poolable = False

现在 Trac 在服务页面后会断开连接,并且数据库上的连接数将保持在较低水平。

但这并非推荐的方法。另请参阅 mod_wsgi 的 IntegrationWithTrac 维基页面底部的注意事项。

其他资源

有关更多故障排除技巧,另请参阅mod_python 故障排除部分,因为大多数与 Apache 相关的问题都非常相似,此外还有关于使用 mod_wsgi 时潜在的应用程序问题的讨论。wsgi 页面还包含一个与 Trac 集成文档。


另请参阅:TracGuide, TracInstall, FastCgi, ModPython, TracNginxRecipe

最后修改 2 年前 最后修改于 2023年06月02日 10:32:55 上午
注意: 查看 TracWiki 获取使用维基的帮助。

© 2025 Oracle 支持 隐私 / 请勿出售我的信息 使用条款 商标政策 自动化访问礼仪