立即注册找回密码

沫娱网

社区官方指定联系方式

工作时间: 周一到周五早上10:00-12:00, 下午03:00-22:00(周六、日不固定)
点击这里给我发消息 点击这里给我发消息 点击这里给我发消息 点击这里给我发消息
QQ: 78646601  71019581  615772376  2581791623   E-Mail: kf@tmicloud.cn
用户交流QQ群
①群416105110 ←提醒: 群内禁止广告, 谢谢合作

外链跳转,保护 Go 跳转,防止被恶意利用

[复制链接]

149

主题

191

帖子

12万

积分

超级管理

Rank: 9Rank: 9Rank: 9

积分
121692
发表于 2019-7-2 09:13:25 | 显示全部楼层 |阅读模式
或是出于优化 SEO,或是出于加强网站体验,很多博客都给文章中的外部链接加上了个二次跳转,本博客也不例外。
比如说我在这插入一个 百度 的超链接,你点击访问后先会被跳转到本博客的跳转页面,一段动画后才会真的转至百度的首页。
看似合情合理,实则暗藏一个小漏洞!
我的思路是这样的:
在跳转页面中,先用 PHP 的‘$_SERVER["HTTP_REFERER"]’函数获取来源链接,然后判断来源链接是不是属于本站,如果不是,再判断跳转链接,如果跳转链接也不属于本站,就给出一个提示:你将要访问的网站不属于本站范围,请谨慎访问。反之则正常跳转。
比方说本站的网址是 http://moyunet.net ,一些二级页面如 http://zb.moyunet.net、https://moyunet.net/about 也属于本站。而 http://www.baidu.com/?moyunet.net 虽然包含“mkblog.cn”,访问后它却是百度的首页。因此不能简单粗暴的通过判断网址中是否存在 “moyunet.net” 来得出结论。
仔细的观察域名的结构你就会发现只要是属于 moyunet.net 的网址一定会满足以下规律:
  • 如果 moyunet.net 的前面有内容,那么一定不会有“?”出现,比如说 abc?.moyunet.net 是不存在的
  • 如果 moyunet.net 的后面还跟有内容,那么一定是“/”,或“?”,比如说 moyunet.net/123 或 moyunet.net?from=123
利用以上两个规律写了个判断函数如下:
[PHP] syntaxhighlighter_viewsource syntaxhighlighter_copycode
/**
 * 判断是不是自己的域名
 * @param $domain 要进行判断的域名
 * @param $my 自己的域名
 * @return 对比结果
 */
function isMyDomain($domain, $my) {
    preg_match('/([^\?]*)/i', $domain, $match);
    if(isset($match[1])) $domain = $match[1];
    preg_match('/([\w-]*\.[\w-]*)\/.*/i', $domain.'/', $match);
    if(isset($match[1]) && $match[1] == $my) return true;
    return false;
}
最终代码
按照以上思路完成整个跳转页面的编写后,测试了一下效果非常不错:只要是从本站点开的跳转网址,都能正常进行跳转,从而第三方打开的跳转,则会弹出提示。
最终完整的跳转页面源代码如下:(代码中的判断思路肯定不唯一,如果您有更好的判断方式,欢迎在下方留言交流!)

[PHP] syntaxhighlighter_viewsource syntaxhighlighter_copycode
<?php  
/** 
 * 带有来路验证和跳转提示功能的跳转页面 
 * @auth 孟坤博客 
 * @authUrl http://mkblog.cn 
 * @data 2017/3/13 
 * @url https://mkblog.cn/701 
 */  
  
// 请将这里的网址改为自己的(顶级)域名地址  
$myDomain = 'mkblog.cn';  
  
// 这里用正则提取 $_SERVER["QUERY_STRING"] 而不是直接 get url  
// 是因为如果链接中自身带有 GET 参数则会导致获取不完整  
preg_match('/url=(.*)/i', $_SERVER["QUERY_STRING"], $jumpUrl);   
  
// 如果没获取到跳转链接,直接跳回首页  
if(!isset($jumpUrl[1])) {  
    header("location:/");  
    exit();  
}  
  
$jumpUrl = $jumpUrl[1];  
  
// 判断是否包含 http:// 头,如果没有则加上  
preg_match('/(http|https):\/\//', $jumpUrl, $matches);      
  
$url = $matches? $jumpUrl: 'http://'. $jumpUrl;  
  
  
// 判断网址是否完整  
preg_match('/[\w-]*\.[\w-]*/i', $url, $matche);      
  
// 是否需要给出跳转提示  
$echoTips = false;  
  
if($matche){  
    // 如果是本站的链接,不展示动画直接跳转  
    if(isMyDomain($url, $myDomain)) {  
        header("location:{$url}");  
        exit();    // 后续操作不再执行  
    }  
      
    $title = '页面加载中,请稍候...';  
    $fromUrl = isset($_SERVER["HTTP_REFERER"])? $_SERVER["HTTP_REFERER"]: ''; // 获取来源url  
      
    // 如果来源和跳转后的地址都不是本站,那么就要给出提示  
    if(!isMyDomain($fromUrl, $myDomain)) {  
        $echoTips = true;  
    }  
} else {    // 网址参数不完整  
    $url = '/';  
    $title = '参数错误,正在返回首页...';  
}  
  
  
/** 
 * 判断是不是自己的域名 
 * @param $domain 要进行判断的域名 
 * @param $my 自己的域名 
 * @return 对比结果 
 */  
function isMyDomain($domain, $my) {  
    preg_match('/([^\?]*)/i', $domain, $match);  
    if(isset($match[1])) $domain = $match[1];  
    preg_match('/([\w-]*\.[\w-]*)\/.*/i', $domain.'/', $match);  
    if(isset($match[1]) && $match[1] == $my) return true;  
    return false;  
}  
  
?>  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<meta http-equiv="X-UA-Compatible" content="IE=edge">  
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">  
<?php  
if($echoTips) {  
    echo '<title>跳转提示</title>';  
} else {  
    echo '<meta http-equiv="refresh" content="0;url='.$url.'">';  
    echo '<title>'.$title.'</title>';  
}  
?>  
<style>  
body{background:#fff;font-family:Microsoft Yahei;-webkit-animation:fadeIn 1s linear;animation:fadeIn 1s linear}  
@-webkit-keyframes fadeIn{from{opacity:0}  
to{opacity:1}  
}@keyframes fadeIn{from{opacity:0}  
to{opacity:1}  
}#circle{background-color:rgba(0,0,0,0);border:5px solid rgba(0,183,229,0.9);opacity:.9;border-right:5px solid rgba(0,0,0,0);border-left:5px solid rgba(0,0,0,0);border-radius:50px;box-shadow:0 0 35px #2187e7;width:50px;height:50px;margin:0 auto;position:fixed;left:30px;bottom:30px;-moz-animation:spinPulse 1s infinite ease-in-out;-webkit-animation:spinPulse 1s infinite ease-in-out;-o-animation:spinPulse 1s infinite ease-in-out;-ms-animation:spinPulse 1s infinite ease-in-out}  
#circle1{background-color:rgba(0,0,0,0);border:5px solid rgba(0,183,229,0.9);opacity:.9;border-left:5px solid rgba(0,0,0,0);border-right:5px solid rgba(0,0,0,0);border-radius:50px;box-shadow:0 0 15px #2187e7;width:30px;height:30px;margin:0 auto;position:fixed;left:40px;bottom:40px;-moz-animation:spinoffPulse 1s infinite linear;-webkit-animation:spinoffPulse 1s infinite linear;-o-animation:spinoffPulse 1s infinite linear;-ms-animation:spinoffPulse 1s infinite linear}  
@-webkit-keyframes spinPulse{0%{-webkit-transform:rotate(160deg);opacity:0;box-shadow:0 0 1px #505050}  
50%{-webkit-transform:rotate(145deg);opacity:1}  
100%{-webkit-transform:rotate(-320deg);opacity:0}  
}@-webkit-keyframes spinoffPulse{0%{-webkit-transform:rotate(0deg)}  
100%{-webkit-transform:rotate(360deg)}  
}#loading-text{position:fixed;left:110px;bottom:35px;color:#736D6D}  
@media screen and (max-width:600px){#circle,#circle1{left:0;right:0;top:0;bottom:0}  
#circle{margin:120px auto}  
#circle1{margin:130px auto}  
#loading-text{display:block;text-align:center;margin-top:220px;position:static;margin-left:10px}  
}  
.warning{max-width: 500px;margin: 20px auto;}  
.wtitle {font-size: 22px;color: #d68300;}  
.wurl {overflow: hidden;text-overflow: ellipsis;white-space: nowrap;color: #827777;}  
.btn {display: inline-block;line-height: 20px;cursor: pointer;border: 1px solid #A9A6A6;padding: 6px 10px;font-size: 14px;text-decoration: none;}  
.btn-green {color: #fff;background-color: #238aca;border: 1px solid #238aca;}  
.btn:hover {background-color: #A9A6A6;border: 1px solid #A9A6A6;color: #fff;}  
</style>  
</head>  
<body>  
    <?php if($echoTips) { ?>  
    <div class="warning">  
        <p class="wtitle">您将要访问:</p>  
        <p class="wurl" title="<?php echo $url;?>"><?php echo $url;?></p>  
        <p>该网站不属于孟坤博客,我们无法确认该网页是否安全,它可能包含未知的安全隐患。</p>  
        <a class="btn btn-green" href="<?php echo $url;?>" rel="nofollow">继续访问</a>  
        <span class="btn">关闭网页</span>  
    </div>  
    <script>  
    function closePage() {  
        // 通用窗口关闭  
        window.opener=null;  
        window.open('','_self');  
        window.close();  
        // 微信浏览器关闭  
        WeixinJSBridge.call('closeWindow');  
    }  
    </script>  
    <?php } else { ?>  
    <div id="circle"></div>  
    <div id="circle1"></div>  
    <p id="loading-text">页面加载中,请稍候...</p>  
    <?php } ?>  
</body>  
</html>  

本文来源于孟坤博客

沫娱网创始人

0

主题

30

帖子

90

积分

注册会员

Rank: 2

积分
90
发表于 2019-7-2 09:16:31 | 显示全部楼层
围观 围观 沙发在哪里!!!
回复

使用道具 举报

0

主题

33

帖子

99

积分

注册会员

Rank: 2

积分
99
发表于 2019-7-2 09:47:29 | 显示全部楼层
为保住菊花,这个一定得回复!
回复

使用道具 举报

0

主题

43

帖子

129

积分

注册会员

Rank: 2

积分
129
发表于 2019-7-2 18:53:01 | 显示全部楼层
为毛老子总也抢不到沙发?!!
回复

使用道具 举报

0

主题

36

帖子

108

积分

注册会员

Rank: 2

积分
108
发表于 2019-7-9 20:06:18 | 显示全部楼层
我擦!我要沙发!
回复

使用道具 举报

0

主题

43

帖子

129

积分

注册会员

Rank: 2

积分
129
发表于 2019-7-10 14:03:33 | 显示全部楼层
站位支持
回复

使用道具 举报

使用高级回帖 (可批量传图、插入视频等)

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则   Ctrl + Enter 快速发布  

发帖时请遵守我国法律,网站会将有关你发帖内容、时间以及发帖IP地址等记录保留,只要接到合法请求,即会将信息提供给有关政府机构。
快速回复 返回顶部 返回列表