我们有一个邮件服务器,我正在尝试编写一个脚本,该脚本将查找具有相似名称的所有用户,以避免恶意用户冒充合法用户。例如,合法用户可能具有james2014@domain.com
的名称,但恶意用户可以注册为james20l4@domain.com
。如果您仔细注意,差异在于我用字母'l'(el)替换了数字'one'。所以我试着写一些可以咨询我的/var/vmail/domain/*
并查找类似名称并提醒我(管理员)的内容。然后我将采取必要的步骤来做我需要的事情。非常感谢任何帮助。
答案 0 :(得分:1)
这样做的一个hacky方法是推导"标准化"您的用户名的版本,将它们作为映射到原始输入的键放在关联数组中,并使用它们来查找问题。
我在下面发布的示例使用bash associative arrays来存储从规范化名称到原始名称的映射,并使用tr
来切换其他字符的某些字符(并完全删除其他字符)。
我假设您的用户列表适合内存;你还需要调整修改和删除字符的映射,以达到你在效果和误报之间最喜欢的平衡。如果您的列表不适合内存,您可以使用单个文件或文件系统来近似它,但老实说,如果您正在处理许多名称,那么使用非shell可能会更好编程语言。
<强>输入:强>
doc
dopey
james2014
happy
bashful
grumpy
james20l4
sleepy
james.2014
sneezy
<强>脚本:强>
#!/bin/bash
# stdin: A list of usernames. stdout: Pairs of names that match.
CHARS_TO_REMOVE="._\\- "
CHARS_TO_MAP_FROM="OISZql"
CHARS_TO_MAP_TO="0152g1"
normalize() {
# stdin: A word. stdout: A modified version of the same word.
exec tr "$CHARS_TO_MAP_FROM" "$CHARS_TO_MAP_TO" \
| tr --delete "$CHARS_TO_REMOVE" \
| tr "A-Z" "a-z"
}
declare -A NORMALIZED_NAMES
while read NAME; do
NORMALIZED_NAME=$(normalize <<< "$NAME")
# -n tests for non-empty strings, as it would be if the name were set already.
if [[ -n ${NORMALIZED_NAMES[$NORMALIZED_NAME]} ]]; then
# This name has been seen before! Print both of them.
echo "${NORMALIZED_NAMES[$NORMALIZED_NAME]} $NAME"
else
# This name has not been seen before. Store it.
NORMALIZED_NAMES["$NORMALIZED_NAME"]="$NAME"
fi
done
<强>输出:强>
james2014 james20l4
james2014 james.2014