التحقق من صحة سلسلة اسم المضيف
-
22-09-2019 - |
سؤال
متابعة تعبير منتظم لمطابقة اسم المضيف أو عنوان 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(".")))
إذا كنت تبحث عن التحقق من صحة اسم المضيف الحالي ، فإن أفضل طريقة هي محاولة حلها. لن تكتب أبدًا تعبيرًا منتظمًا لتوفير هذا المستوى من التحقق من الصحة.