【问题标题】:Matching only leftmost wildcard in the domain name - Python仅匹配域名中最左边的通配符 - Python
【发布时间】:2016-06-19 15:19:20
【问题描述】:

我正在尝试仅为域名中最左侧的通配符编写正则表达式。到目前为止,我有这个:

import re
    o = urlparse(argv[1])
host_name = o.netloc
context = SSL.Context(SSL.TLSv1_METHOD) # Use TLS Method
context.set_options(SSL.OP_NO_SSLv2) # Don't accept SSLv2
context.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
                   callback)
# context.load_verify_locations(ca_file, ca_path)

sock = socket()
ssl_sock = SSL.Connection(context, sock)
ssl_sock.connect((host_name, 443))
ssl_sock.set_connect_state()
ssl_sock.set_tlsext_host_name(host_name)
ssl_sock.do_handshake()

cert = ssl_sock.get_peer_certificate()
common_name = cert.get_subject().commonName.decode()
print "Common Name: ", common_name
print "Cert number: ", cert.get_serial_number()
regex = common_name.replace('.', r'\.').replace('*',r'.*') + '$'
if re.match(regex, host_name):
    print "matches"
else:
    print "invalid"

# output:
Common Name:  *.example.com
Cert number:  63694395280496902491340707875731768741

但是,正则表达式不仅匹配*.example.com,还匹配*.*.*www.*.com。此外,不应允许 https://wrong.host.example.com/ 匹配。如何确保它只匹配最左边的标签?

【问题讨论】:

  • 什么是正确匹配的例子?
  • *.example.com 是有效的正确匹配

标签: python regex http url dns


【解决方案1】:

您可以使用 urlparse 和 split 代替正则表达式。

from urlparse import urlparse
.
.
common_name = cert.get_subject().commonName.decode()
domain = urlparse(common_name).netloc
host = domain.split('.',1)[0]

【讨论】:

    【解决方案2】:

    你可以试试这个正则表达式:

    r'(?:^|\s)(\w+\.)?example\.com(?:$|\s)'
    

    完整演示:

    sock = socket()
    ssl_sock = SSL.Connection(context, sock)
    ssl_sock.connect((host_name, 443))
    ssl_sock.set_connect_state()
    ssl_sock.set_tlsext_host_name(host_name)
    ssl_sock.do_handshake()
    
    cert = ssl_sock.get_peer_certificate()
    common_name = cert.get_subject().commonName.decode()
    print "Common Name: ", common_name
    print "Cert number: ", cert.get_serial_number()
    
    rxString = r'(?:^|\s)(\w+\.)?' + common_name.replace('.', '\.')[3:] + '(?:$|\s)'
    regex = re.compile(rxString)
    
    if regex.match(host_name):
        print "matches"
    else:
        print "invalid"
    

    输入:

    url                
    -------------------
    www.example.com    
    example.com        
    hello.example.com  
    foo.bar.example.com
    *.*.*              
    www.*.com          
    

    输出:

    url                  |  result
    -------------------  |  -----------
    www.example.com      |  matches
    example.com          |  matches
    hello.example.com    |  matches
    foo.bar.example.com  |  invalid
    *.*.*                |  invalid
    www.*.com            |  invalid
    

    【讨论】:

    • Saleem,我如何构建像你这样的正则表达式?我目前是regex = common_name.replace('.', r'\.').replace('*',r'.*') + '$',那么我该如何做类似的事情呢?
    • @philippe 这很简单。我觉得你不用换了。只需将您的 re.match(regex, host_name) 替换为 p.match(host_name),前提是您要复制我的解决方案的前两行
    【解决方案3】:

    不幸的是,在 Saleem 的回答中,Regexp 是错误的并且不符合 RFC6125[6.4.3]。

    1. “example.com”和“.example.com”均不得匹配。
    2. 可以有这样的通配符:f*.example.com。
    3. 不应在字符串的前面和结尾出现任何空格 (\s) 字符。

    我认为,最好的方法是用 '[^.]+' (或 '[^.]*' 更改 '*' 字符 - 如果 f.example.com 与 f*. example.com 与否):

    rxString = '^'+common_name.replace('.','\.').replace('*','[^\.]+')+'$'
    

    【讨论】:

      猜你喜欢
      • 2018-03-22
      • 1970-01-01
      • 1970-01-01
      • 2017-06-17
      • 2012-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多