验证主机名字符串

kos*_*tmo 24 python regex validation hostname fqdn

跟随正则表达式匹配主机名或IP地址? 并使用有效主机名的限制作为参考,在Python中匹配/验证主机名/ fqdn(完全限定域名)的最可读,最简洁的方法是什么?我已经回答了下面的尝试,欢迎改进.

Tim*_*ker 48

import re
def is_valid_hostname(hostname):
    if len(hostname) > 255:
        return False
    if hostname[-1] == ".":
        hostname = hostname[:-1] # strip exactly one dot from the right, if present
    allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
    return all(allowed.match(x) for x in hostname.split("."))
Run Code Online (Sandbox Code Playgroud)

确保每个细分

  • 包含至少一个字符,最多包含63个字符
  • 仅包含允许的字符
  • 不以连字符开头或结尾.

它也避免了双重否定(not disallowed),如果hostname以a结尾.,那也没关系.如果hostname以多个点结束,它将(并且应该)失败.

  • @Tim Pietzcker是的,最后一个点是合法的.它将该名称标记为完全限定的域名,这使DNS系统知道不应尝试将本地域附加到该域名. (5认同)

Eug*_*ash 8

这是Tim Pietzcker 答案的更严格版本,并进行了以下改进:

  • 将主机名的长度限制为 253 个字符(在去除可选的尾随点之后)。
  • 将字符集限制为 ASCII(即使用[0-9]而不是\d)。
  • 检查 TLD 是否不是全数字。
import re

def is_valid_hostname(hostname):
    if hostname[-1] == ".":
        # strip exactly one dot from the right, if present
        hostname = hostname[:-1]
    if len(hostname) > 253:
        return False

    labels = hostname.split(".")

    # the TLD must be not all-numeric
    if re.match(r"[0-9]+$", labels[-1]):
        return False

    allowed = re.compile(r"(?!-)[a-z0-9-]{1,63}(?<!-)$", re.IGNORECASE)
    return all(allowed.match(label) for label in labels)
Run Code Online (Sandbox Code Playgroud)

  • 根据 RFC 3936 ( https://tools.ietf.org/html/rfc3696#section-2 ),只有 TLD 不应该是数字,所以我会说最后一个条件应该看起来像 `if re.match(r "\.(\d+)$", 主机名):` (2认同)

tot*_*ico 6

不要重新发明轮子。您可以使用库,例如​​验证器。或者你可以复制他们的代码

安装

pip install validators
Run Code Online (Sandbox Code Playgroud)

用法

import validators
if validators.domain('example.com')
    print('this domain is valid')
Run Code Online (Sandbox Code Playgroud)

  • 这很酷,但还不够。域不是主机名。`validators.domain('localhost')` 失败。 (3认同)

sol*_*ack 5

根据The Old New Thing,DNS名称的最大长度为253个字符。(一个最多允许255个八位位组,但其中两个被编码占用。)

import re

def validate_fqdn(dn):
    if dn.endswith('.'):
        dn = dn[:-1]
    if len(dn) < 1 or len(dn) > 253:
        return False
    ldh_re = re.compile('^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$',
                        re.IGNORECASE)
    return all(ldh_re.match(x) for x in dn.split('.'))
Run Code Online (Sandbox Code Playgroud)

可以根据自己的目的主张是否接受空域名。