سؤال

متابعة تعبير منتظم لمطابقة اسم المضيف أو عنوان IP؟واستخدام قيود على أسماء مضيف صالحة كمرجع ، ما هي الطريقة الأكثر قابلية للقراءة والموجزة لمطابقة/التحقق من صحة اسم المضيف/FQDN (اسم المجال المؤهل بالكامل) في بيثون؟ لقد أجبت مع محاولتي أدناه ، والتحسينات موضع ترحيب.

هل كانت مفيدة؟

المحلول

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("."))

يضمن كل جزء

  • يحتوي على حرف واحد على الأقل وحد أقصى 63 حرفًا
  • يتكون فقط من الشخصيات المسموح بها
  • لا تبدأ أو تنتهي مع الواصلة.

كما أنه يتجنب السلبيات المزدوجة (not disallowed)، و إذا hostname ينتهي في ., ، هذا جيد أيضًا. سوف تفشل (وينبغي) إذا hostname ينتهي في أكثر من نقطة واحدة.

نصائح أخرى

لكل الشيء الجديد القديم, ، الحد الأقصى لطول اسم 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('.'))

يمكن للمرء أن يجادل لقبول أسماء النطاق الفارغة ، أو لا ، اعتمادًا على الغرض من الفرد.

إليك نسخة أكثر صرامة من إجابة تيم بيتزكر مع التحسينات التالية:

  • الحد من طول اسم المضيف إلى 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)

أحب دقة إجابة تيم بيتزكر ، لكنني أفضل إلغاء تحميل بعض المنطق من التعبيرات العادية لقدرة على القراءة. بصراحة ، كان علي أن أبحث عن معنى هؤلاء (? أجزاء "تدوين التمديد". بالإضافة إلى ذلك ، أشعر أن النهج "السلبي المزدوج" أكثر وضوحًا من حيث أنه يحد من مسؤولية التعبير العادي إلى مجرد العثور على أي حرف غير صالح. أنا أحب أن re.ignorecase يتيح تقصير regex.

إذن هذه لقطة أخرى. إنه أطول ولكنه يقرأ نوعًا من النثر. أفترض أن "قابلة للقراءة" يتعارض إلى حد ما مع "موجزة". أعتقد أن جميع قيود التحقق من الصحة المذكورة في الخيط حتى الآن مغطاة:


def isValidHostname(hostname):
    if len(hostname) > 255:
        return False
    if hostname.endswith("."): # A single trailing dot is legal
        hostname = hostname[:-1] # strip exactly one dot from the right, if present
    disallowed = re.compile("[^A-Z\d-]", re.IGNORECASE)
    return all( # Split by labels and verify individually
        (label and len(label) <= 63 # length is within proper range
         and not label.startswith("-") and not label.endswith("-") # no bordering hyphens
         and not disallowed.search(label)) # contains only legal characters
        for label in hostname.split("."))
def is_valid_host(host):
    '''IDN compatible domain validator'''
    host = host.encode('idna').lower()
    if not hasattr(is_valid_host, '_re'):
        import re
        is_valid_host._re = re.compile(r'^([0-9a-z][-\w]*[0-9a-z]\.)+[a-z0-9\-]{2,15}$')
    return bool(is_valid_host._re.match(host))

مجانية للإجابة timpietzcker.دون النطاق هو حرف مضيف صالح (ولكن ليس لاسم المجال). في حين تم العثور على اندفاعة مزدوجة عادة في مجال IDN PunyCode (على سبيل المثال XN--). يجب تجريد رقم المنفذ. هذا هو تنظيف الكود.

import re
def is_valid_hostname(hostname):
    if len(hostname) > 255:
        return False
    hostname = hostname.rstrip(".")
    allowed = re.compile("(?!-)[A-Z\d\-\_]{1,63}(?<!-)$", re.IGNORECASE)
    return all(allowed.match(x) for x in hostname.split("."))

# convert your unicode hostname to punycode (python 3 ) 
# Remove the port number from hostname
normalise_host = hostname.encode("idna").decode().split(":")[0]
is_valid_hostanme(normalise_host )

أعتقد أن هذا regex قد يساعد في Python: '^([A-ZA-Z0-9]+(. | -))*[A-ZA-Z0-9]+$'

معالجة كل تسمية DNS بشكل فردي عن طريق استبعاد الأحرف غير صالحة وضمان الطول غير الصفر.


def isValidHostname(hostname):
    disallowed = re.compile("[^a-zA-Z\d\-]")
    return all(map(lambda x: len(x) and not disallowed.search(x), hostname.split(".")))

إذا كنت تبحث عن التحقق من صحة اسم المضيف الحالي ، فإن أفضل طريقة هي محاولة حلها. لن تكتب أبدًا تعبيرًا منتظمًا لتوفير هذا المستوى من التحقق من الصحة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top