Apache、LDAP 和 WSGI 编码问题
Apache, LDAP and WSGI encoding issue
我在 Ubuntu 14.04.2 (x86_64) 和 python 3.4.0 上使用 Apache 2.4.7 和 mod_wsgi 3.4。我的 python 应用程序依靠 apache 对我们公司的 LDAP 服务器 (MS Active Directory 2008) 执行用户身份验证。它还使用 OS 环境将一些额外的 LDAP 数据传递给 python 应用程序。在 apache 配置中,我像这样查询 LDAP:
…
AuthLDAPURL "ldap://server:389/DC=company,DC=lokal?sAMAccountName,sn,givenName,mail,memberOf?sub?(objectClass=*)"
AuthLDAPBindDN …
AuthLDAPBindPassword …
AuthLDAPRemoteUserAttribute sAMAccountName
AuthLDAPAuthorizePrefix AUTHENTICATE_
…
这会将一些用户数据传递到我的 WSGI 脚本,我在其中按如下方式处理信息:
# Make sure the packages from the virtualenv are found
import site
site.addsitedir('/home/user/.virtualenvs/ispot-cons/lib/python3.4/site-packages')
# Patch path for app (so that libispot can be found)
import sys
sys.path.insert(0, '/var/www/my-app/')
import os
from libispot.web import app as _application
def application(environ, start_response):
os.environ['REMOTE_USER'] = environ.get('REMOTE_USER', "")
os.environ['REMOTE_USER_FIRST_NAME'] = environ.get('AUTHENTICATE_GIVENNAME', "")
os.environ['REMOTE_USER_LAST_NAME'] = environ.get('AUTHENTICATE_SN', "")
os.environ['REMOTE_USER_EMAIL'] = environ.get('AUTHENTICATE_MAIL', "")
os.environ['REMOTE_USER_GROUPS'] = environ.get('AUTHENTICATE_MEMBEROF', "")
return _application(environ, start_response)
然后我可以使用 os.environ.get(…)
在我的 python 应用程序中访问此信息。 (顺便说一句:如果您有更优雅的解决方案,请告诉我!)
问题是某些用户名包含未正确编码的特殊字符(德语变音符号,例如 äöüÄÖÜ
)。因此,例如,名称 Tölle
作为 Tölle
.
到达我的 python 应用程序
很明显,这是一个编码问题,因为
$ echo "Tölle" | iconv --from utf-8 --to latin1
给出了正确的 Tölle
。
另一个可能有帮助的观察:在我的 apache 日志中,我发现字符 ü
表示为 \xc3\x83\xc2\xbc
。
我在 /etc/apache2/envvars
中告诉我的 Apache 使用 LANG=de_DE.UTF-8
并且 python 3 也支持 utf-8。我似乎无法指定有关我的 LDAP 服务器的任何信息。所以我的问题是:编码在哪里混淆了,我该如何修复它?
在每个请求上将值复制到 os.environ
是不好的做法,因为如果 WSGI 服务器是 运行 多线程配置,并且并发请求相互干扰,这将失败得很惨。改为查看线程局部变量。
关于LDAP的编码数据问题,如果我理解这个问题,你需要做的是:
"Tölle".encode('latin-1').decode('utf-8')
我在 Ubuntu 14.04.2 (x86_64) 和 python 3.4.0 上使用 Apache 2.4.7 和 mod_wsgi 3.4。我的 python 应用程序依靠 apache 对我们公司的 LDAP 服务器 (MS Active Directory 2008) 执行用户身份验证。它还使用 OS 环境将一些额外的 LDAP 数据传递给 python 应用程序。在 apache 配置中,我像这样查询 LDAP:
…
AuthLDAPURL "ldap://server:389/DC=company,DC=lokal?sAMAccountName,sn,givenName,mail,memberOf?sub?(objectClass=*)"
AuthLDAPBindDN …
AuthLDAPBindPassword …
AuthLDAPRemoteUserAttribute sAMAccountName
AuthLDAPAuthorizePrefix AUTHENTICATE_
…
这会将一些用户数据传递到我的 WSGI 脚本,我在其中按如下方式处理信息:
# Make sure the packages from the virtualenv are found
import site
site.addsitedir('/home/user/.virtualenvs/ispot-cons/lib/python3.4/site-packages')
# Patch path for app (so that libispot can be found)
import sys
sys.path.insert(0, '/var/www/my-app/')
import os
from libispot.web import app as _application
def application(environ, start_response):
os.environ['REMOTE_USER'] = environ.get('REMOTE_USER', "")
os.environ['REMOTE_USER_FIRST_NAME'] = environ.get('AUTHENTICATE_GIVENNAME', "")
os.environ['REMOTE_USER_LAST_NAME'] = environ.get('AUTHENTICATE_SN', "")
os.environ['REMOTE_USER_EMAIL'] = environ.get('AUTHENTICATE_MAIL', "")
os.environ['REMOTE_USER_GROUPS'] = environ.get('AUTHENTICATE_MEMBEROF', "")
return _application(environ, start_response)
然后我可以使用 os.environ.get(…)
在我的 python 应用程序中访问此信息。 (顺便说一句:如果您有更优雅的解决方案,请告诉我!)
问题是某些用户名包含未正确编码的特殊字符(德语变音符号,例如 äöüÄÖÜ
)。因此,例如,名称 Tölle
作为 Tölle
.
很明显,这是一个编码问题,因为
$ echo "Tölle" | iconv --from utf-8 --to latin1
给出了正确的 Tölle
。
另一个可能有帮助的观察:在我的 apache 日志中,我发现字符 ü
表示为 \xc3\x83\xc2\xbc
。
我在 /etc/apache2/envvars
中告诉我的 Apache 使用 LANG=de_DE.UTF-8
并且 python 3 也支持 utf-8。我似乎无法指定有关我的 LDAP 服务器的任何信息。所以我的问题是:编码在哪里混淆了,我该如何修复它?
在每个请求上将值复制到 os.environ
是不好的做法,因为如果 WSGI 服务器是 运行 多线程配置,并且并发请求相互干扰,这将失败得很惨。改为查看线程局部变量。
关于LDAP的编码数据问题,如果我理解这个问题,你需要做的是:
"Tölle".encode('latin-1').decode('utf-8')