我有一台 Apache Web 服务器,它使用 Basic Auth 和 LDAP 后端来验证用户身份。用户名与 LDAP 的匹配不区分大小写,因此同一个用户可以以abc
、Abc
、ABC
等身份登录。
但是 Apache 背后的应用程序(我无法更改)以区分大小写的方式使用该用户名,这导致数据不一致。
Authorization
我发现了一个带有答案的老问题,它表明可以通过使用一些 Apache 配置和自定义程序修改标头来解决这个问题RewriteMap
:使用 Apache 进行不区分大小写的基本身份验证
所以我编写了一个程序将 base64 编码的UsEr:PaSs
值转换为user:PaSs
,但我不知道如何将其集成到 Apache 配置中。
RewriteRule
我尝试使用带有或 的地图RequestHeader
,但它不起作用:
RewriteEngine on
RewriteMap UserToLower "prg:C:/apache/UserToLower.exe"
# RequestHeader set Authorization "${UserToLower:%{HTTP:Authorization}}"
# RewriteRule "(.*)" "${UserToLower:%{HTTP:Authorization}}"
感谢您的帮助!
我知道还有另一种方法,即使用 Perl 脚本来操作标头。但我不喜欢该解决方案,因为那样的话我就需要安装 Perl 和额外的 Apache 模块。
编辑
有了 Gerard 的回答,我能够修改Authorization
标头。我无法让 Apache 接受修改后的标头。因此,现在用户名中包含大写字母的用户将被拒绝,而不是通过将其转换为小写来修复用户名。这确保了数据完整性,所以我对这种解决方法很满意。
这是我用于重写映射的 C# 代码:
/*
* compile with:
* C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /target:winexe UserToLower.cs
*/
using System;
using System.IO;
using System.Text;
/**
* Map username in HTTP Basic Auth to lowercase.
*/
class UserToLower {
static string decode(string encoded) {
byte[] decodedBytes = Convert.FromBase64String(encoded);
string decodedString = Encoding.UTF8.GetString(decodedBytes);
return decodedString;
}
static string encode(string decoded) {
byte[] encodedBytes = Encoding.UTF8.GetBytes(decoded);
string encodedString = Convert.ToBase64String(encodedBytes);
return encodedString;
}
static string modifyAuth(string encodedAuthStr) {
string[] parts = decode(encodedAuthStr).Split(':');
parts[0] = parts[0].ToLower();
string newAuthString = encode(String.Join(":", parts));
return newAuthString;
}
static void Main() {
string line;
while ((line = Console.ReadLine()) != null) {
string result;
if (line.StartsWith("Basic ")) {
try {
result = "Basic " + modifyAuth(line.Substring(6)) + '\n';
} catch {
result = line + '\n';
}
// FIXME: remove this hack which keeps out users with unacceptable username
if (line + '\n' != result) {
result = "Basic SU5WQUxJRDpJTlZBTElECg==\n"; // INVALID:INVALID
}
} else {
result = line + '\n';
}
Console.Write(result);
// File.AppendAllText(@"logs/UserToLower.log", line + " ---> " + result);
}
}
}
这是我的 Apache 配置:
<IfModule rewrite_module>
<IfModule headers_module>
RewriteEngine on
RewriteMap UserToLower "prg:C:/apache/UserToLower.exe"
RewriteRule .* - [E=EX:${UserToLower:%{http:Authorization}}]
RequestHeader set Authorization "%{EX}e"
</IfModule>
</IfModule>
答案1
使用以下 RewriteMap /usr/local/bin/X.sh:
#! /usr/bin/ksh
typeset -u XU
while read X
do
XD=$(expr "$X" : "Basic \(.*\)" | base64 -d)
XU=$(expr "$XD" : "\(.*\):")
XP=$(expr "$XD" : ".*:\(.*\)")
XN="Basic $(echo $XU:$XP | base64)"
echo "${XN}"
done
以及以下 Apache 配置
RewriteEngine on
RewriteMap rmx "prg:/usr/local/bin/X.sh"
<Location ~ "(?i)php$">
AuthType basic
AuthName "phprivate area"
AuthUserFile "/etc/apache2/passwd"
Require valid-user
RewriteRule .* - [E=EX:${rmx:%{http:Authorization}}]
RequestHeader set Authorization %{EX}e
</Location>
用户名已更改为大写。