使用PHP验证URL并仅返回主机域名。
我想验证一个域名,然后将主域名分条返回到example.co.uk 我已经从各种来源的帮助开始了,并且可以通过.com、.net、.org、.info和所有的.uk来实现这一点使用PHP验证URL并仅返回主机域名。,php,Php,我想验证一个域名,然后将主域名分条返回到example.co.uk 我已经从各种来源的帮助开始了,并且可以通过.com、.net、.org、.info和所有的.uk来实现这一点 $targetUrl = 'http://sub.example.uk/test/'; $host = filter(get_domain($targetUrl)); function filter($domain){ if($domain){ $domain_array = explode
$targetUrl = 'http://sub.example.uk/test/';
$host = filter(get_domain($targetUrl));
function filter($domain){
if($domain){
$domain_array = explode(".", $domain);
$domain_count = count($domain_array);
$domain_last = end($domain_array);
$domain_first = $domain_array[0];
$domain_second = $domain_array[1];
$domain_second_last = array_slice($domain_array, -2, 1);
$domain_second_last = $domain_second_last[0];
$domain_third_last = array_slice($domain_array, -3, 1);
$domain_third_last = $domain_third_last[0];
// UK Validation
$uk_second = array('ac', 'co', 'gov', 'judiciary', 'ltd', 'me', 'mod', 'net', 'nhs', 'nic', 'org', 'parliament', 'plc', 'police', 'sch');
if($domain_last == 'uk'){
if($domain_count == '2'){
// if domain.uk
return $domain;
}elseif(in_array($domain_second, $uk_second)){
//if domain.$uk_second.uk
return $domain;
}elseif(in_array($domain_second_last, $uk_second)){
// if subdomain on 2 dd.dd.co.uk rename to dd.co.uk
$domain = $domain_third_last.'.'.$domain_second_last.'.'.$domain_last;
return $domain;
}else{
// finaly it must be a dsd.sds.uk so lets remove the subdomain
$domain = $domain_second_last.'.'.$domain_last;
return $domain;
}
}
// END .UK
// SImple Single TLDs
$single_tlds = array('com', 'net', 'org', 'info');
if(in_array($domain_last, $single_tlds)){
if($domain_count == '2'){
// simple is it a ddd.com
return $domain;
}else{
$domain = $domain_second_last.'.'.$domain_last;
return $domain;
}
}
}//if domain
}
function get_domain($domain) {
$domain = strtolower($domain);
if (!filter_var($domain, FILTER_VALIDATE_URL) === false) {
$urlParts = parse_url($domain);
$domain = $urlParts['host'];
$domain = str_ireplace('www.','',$domain);
$original = $domain = strtolower($domain);
if (filter_var($domain, FILTER_VALIDATE_IP)) { return $domain; }
$arr = array_slice(array_filter(explode('.', $domain, 4), function($value){
return $value !== 'www'; }), 0); //rebuild array indexes
if (count($arr) > 2) {
$count = count($arr);
$_sub = explode('.', $count === 4 ? $arr[3] : $arr[2]);
if (count($_sub) === 2) { // two level TLD
$removed = array_shift($arr);
if ($count === 4) // got a subdomain acting as a domain
$removed = array_shift($arr);
}
elseif (count($_sub) === 1){ // one level TLD
$removed = array_shift($arr); //remove the subdomain
if (strlen($_sub[0]) === 2 && $count === 3) // TLD domain must be 2 letters
array_unshift($arr, $removed);
else{
// non country TLD according to IANA
$tlds = array( 'aero', 'arpa', 'asia', 'biz', 'cat', 'com', 'coop', 'edu', 'gov', 'info', 'jobs', 'mil', 'mobi', 'museum', 'name', 'net', 'org', 'post', 'pro', 'tel', 'travel', 'xxx', );
if (count($arr) > 2 && in_array($_sub[0], $tlds) !== false) {//special TLD don't have a country
array_shift($arr);
}
}
}
else { // more than 3 levels, something is wrong
for ($i = count($_sub); $i > 1; $i--)
$removed = array_shift($arr);
}
}
elseif (count($arr) === 2) {
$arr0 = array_shift($arr);
if (strpos(join('.', $arr), '.') === false
&& in_array($arr[0], array('localhost','test','invalid')) === false) // not a reserved domain
{
// seems invalid domain, restore it
array_unshift($arr, $arr0);
}
}
return join('.', $arr);
}
}
它的可伸缩性不是很好,我必须遍历所有的域后缀并添加它们。我相信一定有更简单的方法?有人能帮忙吗?也许可以通过某种方式从中加载列表
因此,对于一系列数据和结果,我希望看到的是:
http://subdomain.example.co.uk/path/site.php -> example.co.uk
http://subdomain.example.uk/path/site.php -> example.uk
www.subdomain.example.uk/path/site.php -> example.uk
subdomain.example.uk -> example.uk
http://gobble.gobble.notavalidsuffix -> false
给你:
给你:
事实上,在PHP中验证url是一项复杂的任务 您可以使用内置的和函数,但正如PHP.net上的许多用户评论,甚至文档所指出的那样,它们并不十分可靠 首先,它们不支持国际化域名(URL包含非ASCII字符,例如Unicode字符) 请注意,该函数将只查找有效的ASCII URL国际化域名(包含非ASCII字符)将失败 另一方面,他们通过了很多误报 请注意,有效的URL可能未指定HTTP协议HTTP://因此可能需要进一步验证以确定URL是否使用预期的协议,例如ssh://或mailto: 它们也没有有效的名称扩展名列表。这意味着类似于
asdf://asdf.asdf
通过filter\u var。我试过了,实际上是这样
filter\u var
也可能是一个潜在的XSS漏洞,因为它传递类似j的信息avascript://comment%0Aalert(1) “您好
有效
很抱歉,这是一个坏消息,但这是事实。我确实发现了一些PHP验证库,其中包括url,但它们仍然基于parse\u url
或filter\u var
。我也不相信regex能胜任这项工作
然而,(plug time:)我正在开发一个PHP库,它应该能够实现您想要的,我希望在几天内完成它。事实是,在PHP中验证url是一项复杂的任务 您可以使用内置的和函数,但正如PHP.net上的许多用户评论,甚至文档所指出的那样,它们并不十分可靠 首先,它们不支持国际化域名(URL包含非ASCII字符,例如Unicode字符) 请注意,该函数将仅查找有效的ASCII URL;国际化域名(包含非ASCII字符)将失败 另一方面,他们通过了很多误报 请注意,有效的URL可能未指定HTTP协议HTTP://因此可能需要进一步验证以确定URL是否使用预期的协议,例如ssh://或mailto: 它们也没有有效的名称扩展名列表。这意味着类似于
asdf://asdf.asdf
通过filter\u var。我试过了,实际上是这样
filter\u var
也可能是一个潜在的XSS漏洞,因为它传递类似j的信息avascript://comment%0Aalert(1) “您好
有效
很抱歉,我带来了坏消息,但这是事实。我确实在PHP中发现了许多包含url的验证库,但它们都是基于parse\u url
或filter\u var
构建的。我也不相信regex能胜任这份工作
然而,(plug time:)我正在开发一个PHP库,它应该能够实现您想要的,我希望在几天内完成它 下面将通过剥离不必要的URL参数等来验证URL。。然后将此字符串传递到
gethostbyname()
。然后,这将查询给定根域的DNS服务器,如果成功,将向您返回IP,如果不成功,将返回相同的输入字符串。然后,我将这个结果传递到一个过滤器中,该过滤器验证IP字符串。如果成功,它将以给定的格式返回域。只需确保您指向的DNS提供商不会解析每个DNS查找…例如,我在英国的ISP会自动解析每个失败的DNS查找,并使用有效的a记录,该记录会解析为显示“无此类网页”的网页。谷歌DNS工作正常,所以如果可以,请使用它
function validDom($url) {
$newUrl = (filter_var($url, FILTER_VALIDATE_URL)) ? $url : FALSE;
if ($newUrl === FALSE) {
return FALSE;
}
$urlSplit = explode('/', $newUrl);
foreach ($urlSplit as $k=>$v) {
if(substr_count($v, '.') >= 2) {
$newUrl = $v;
}
}
$cleanDomain = substr_replace($newUrl, '', 0, strpos($newUrl, '.')+1);
$chkDNS = gethostbyname($cleanDomain);
if (filter_var($chkDNS, FILTER_VALIDATE_IP) !== FALSE) {
return $cleanDomain;
}
return false;
}
测试域
$domainArr = [
'https://www.facebook.com',
'https://www.care.org.uk',
'https://www.facebook.co.uk',
'https://www.google.com/dfsdfsdfsd/sdfsdf',
'https://sub.fsdfsdfsdfsdfsd.co.uk/dfsdfsdf',
'https://www.nhs.uk/dfsdfsdfsdfsd?fgfg=fgfg',
'javascript://comment%0Aalert(1)"hello',
];
foreach($domainArr as $k=>$v) {
var_dump(validDom($v));
echo '<br>';
}
编辑:
此功能还可以解决由于
j而绕过FILTER\u VALIDATE\u URL
的恶意代码问题avascript://comment%0Aalert(1)“您好”
未通过DNS解析,最终导致失败 下面将通过剥离不必要的URL参数等来验证URL。。然后将此字符串传递到gethostbyname()
。然后,这将查询给定根域的DNS服务器,如果成功,将向您返回IP,如果不成功,将返回相同的输入字符串。然后,我将这个结果传递到一个过滤器中,该过滤器验证IP字符串。如果成功,它将以给定的格式返回域。只需确保您指向的DNS提供商不会解析每个DNS查找…例如,我在英国的ISP会自动解析每个失败的DNS查找,并使用有效的a记录,该记录会解析为显示“无此类网页”的网页。谷歌DNS工作正常,所以如果可以,请使用它
function validDom($url) {
$newUrl = (filter_var($url, FILTER_VALIDATE_URL)) ? $url : FALSE;
if ($newUrl === FALSE) {
return FALSE;
}
$urlSplit = explode('/', $newUrl);
foreach ($urlSplit as $k=>$v) {
if(substr_count($v, '.') >= 2) {
$newUrl = $v;
}
}
$cleanDomain = substr_replace($newUrl, '', 0, strpos($newUrl, '.')+1);
$chkDNS = gethostbyname($cleanDomain);
if (filter_var($chkDNS, FILTER_VALIDATE_IP) !== FALSE) {
return $cleanDomain;
}
return false;
}
测试域
$domainArr = [
'https://www.facebook.com',
'https://www.care.org.uk',
'https://www.facebook.co.uk',
'https://www.google.com/dfsdfsdfsd/sdfsdf',
'https://sub.fsdfsdfsdfsdfsd.co.uk/dfsdfsdf',
'https://www.nhs.uk/dfsdfsdfsdfsd?fgfg=fgfg',
'javascript://comment%0Aalert(1)"hello',
];
foreach($domainArr as $k=>$v) {
var_dump(validDom($v));
echo '<br>';
}
编辑:
此功能还可以解决由于
j而绕过FILTER\u VALIDATE\u URL
的恶意代码问题avascript://comment%0Aalert(1)“您好”
未通过DNS解析,最终导致失败 这里的确切问题是什么?这里的确切问题是什么?@shalvah的问题不是很清楚。域名必须包含一些后缀吗?还有什么其他要求?@shalvah的问题不是很清楚。必须域na