js全局监听a标签跳转前拦截统一跳转到指定页面进行数据处理

发布时间 2023-04-06 17:28:23作者: 且行且思

在现有大多数阅读性文章、博客等内容,不单有图文结合的形式让内容更加饱满更有关联链接来充实文章的真实、准确性。那么当这些连接进行跳转离开网站时,我们要如何确认即将前往网站的安全性呢?

 

跳转效果演示——点击进入码云官网

本文就该问题,使用js代码全局监听a标签跳转前进行跳转拦截。提取跳转连接,统一跳转到指定页面进行提示及跳转链接安全审核。

先来看看完整代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <a href="https://tool.xuexiareas.com/" target="_blank">六月初工具站</a>

<a href="https://www.baidu.com/" target="_blank">baidu</a>
        <script>
            document.body.addEventListener("click",function (event) {
                    var target = event.target || event.srcElement;      // 兼容处理
                    if (target.nodeName.toLocaleLowerCase() === "a") {    // 判断是否匹配目标元素
                        if (event.preventDefault) {     // 对捕获到的 a 标签进行处理
                            event.preventDefault();
                        } else {
                            window.event.returnValue = true;
                        }
                        choosePush(target); // 处理完 a 标签的内容,重新触发跳转,根据原来 a 标签页 target 来判断是否需要新窗口打开
                    }
                }.bind(this)
            );
            function choosePush(el) {
                const target = el.getAttribute("target");
                const href = el.getAttribute("href");
                if (target === "_blank") {
                    window.open('https://www.xuexiareas.com/link.html?target='+ encodeURIComponent(href));   
                } else {
                    window.location.href = href;
                }
            }
        </script>
    </body>
</html>

 

中间安全提示页:

<!DOCTYPE html>
<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">
        <meta name="referrer" content="always">
        
        <title>网站跳转中心-六月初博客站</title>
        <style>
            html,
            body {
                background: #F3F4F5;
                font-family: PingFang SC, Hiragino Sans GB, Arial, Microsoft YaHei, Verdana, Roboto, Noto, Helvetica Neue, sans-serif;
                padding: 0;
                margin: 0;
                height: 100vh;
                width: 100vw;
                overflow: hidden;
            }
            a {
                text-decoration: none;
            }
            #linkPage{
                height: 100vh;
                width: 100vw;
                overflow: hidden;
                display: flex;
                align-items: center;
                justify-content: center;
                margin-top: -10%;
            }
            .content {
                width: 450px;
                margin: auto;
                word-break: break-all;
            }

            .content .logo-img img {
                display: block;
                width: 175px;
                margin: auto;
                margin-bottom: 16px;
            }

            .content .loading-item {
                background: #fff;
                padding: 24px;
                border-radius: 12px;
                border: 1px solid #E1E1E1;
            }

            .content .flex {
                display: flex;
                align-items: center;
            }

            .content .flex-end {
                display: flex;
                justify-content: flex-end;
                align-items: center;
            }


            .content .tip2 {
                background: #ecfaf8;
            }



            .content .loading-color2 {
                color: #09a88c;
            }

            .content .loading-tip {
                padding: 12px;
                margin-bottom: 16px;
                border-radius: 4px;
            }

            .content .loading-topic {
                font-size: 14px;
                color: #222226;
                line-height: 24px;
                margin-bottom: 24px;
            }

            .content .loading-img {
                width: 24px;
                height: 24px;
            }

            .content .loading-btn {
                white-space: nowrap;
                font-size: 14px;
                color: #09a88c;
                border: 1px solid #09a88c;
                display: inline-block;
                box-sizing: border-box;
                padding: 6px 18px;
                border-radius: 18px;
                margin-left: 8px;
            }
            .content .cancle-btn{
                white-space: nowrap;
                font-size: 14px;
                color: #c7c7c7;
                border: 1px solid #c7c7c7;
                display: inline-block;
                box-sizing: border-box;
                padding: 6px 18px;
                border-radius: 18px;
                margin-left: 8px;
            }


            .content .loading-text {
                font-size: 16px;
                font-weight: 600;
                color: #222226;
                line-height: 22px;
                margin-left: 12px;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }

            @media (max-width: 450px) {
                .content {
                    width: 94%;
                }
            }

        </style>
    </head>
    <body>
        <div id="linkPage" class="link-page">
            <div class="content">
                <div class="logo-img"><img src="./static/logo_text.png" alt=""></div>

                <div class="loading-item loading-others">
                    <div class="flex loading-tip tip2"> <img class="loading-img"
                            src="./static/warning20201108.png" alt="">
                        <div class="loading-text">请注意您的账号和财产安全</div>
                    </div>
                    <div class="loading-topic"><span>您即将离开六月初博客站,去往:</span><a
                            class="loading-color2" id="setUrl">https://tool.xuexiareas.com/</a> </div>
                    <div class="flex-end">
                        <a class="cancle-btn" href="javascript:window.opener=null;window.close();">取消</a> 
                            <a class="loading-btn" id="setA" href="https://tool.xuexiareas.com/" target="_self">继续</a>
                        </div>
                </div>
            </div>
        </div>
        <script>

            window.onload = function(){
                if(getQueryString('target')){
                    document.getElementById('setUrl').innerHTML= getQueryString('target')
                    document.getElementById('setA').href= getQueryString('target')
                    if(getQueryString('target').slice(0, 27) == 'https://tool.xuexiareas.com'){
                        document.getElementById('setA').click()
                    }
                }else{
                    document.getElementById('setA').href= 'https://tool.xuexiareas.com/'
                    document.getElementById('setUrl').innerHTML= 'https://tool.xuexiareas.com/'
                }
            }
            function getQueryString(name) { 
              var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象  
              var r = window.location.search.substr(1).match(reg);  //匹配目标参数
              if( r != null ) return decodeURIComponent( r[2] ); return null;   
            }
        </script>
    </body>
</html>

 

js代码解析:

    1、对body进行全局监听

    2、当body区域有点击效果时,提取点击的节点是否是a标签

    3、阻止默认a标签的原生跳转

    4、提取a标签的相关数据,进行自定义从新跳转

通过以上四个步骤,js实现了对全局a标签的跳转监听、阻止效果。提取到跳转参数后,可以统一跳转到指定路径去进行二次确认跳转及跳转路径安全的验证。