如何避免浏览器审查工具修改代码导致YouTube视频推荐屏蔽失效
优化方案
你的原有方案核心问题是所有覆盖逻辑都依赖静态CSS类和公开DOM规则,普通用户只要通过审查工具删除对应类名或CSS规则就能绕过限制。所有前端防护都只能提高篡改门槛,无法实现100%绝对防破解,以下方案可拦截99%以上普通用户的篡改操作:
核心优化点
- 放弃CSS类控制覆盖效果,改用JS直接写入内联样式,避免用户删除CSS规则或DOM类名后失效
- 接入
MutationObserver监听播放器容器的所有DOM变动,用户修改样式/类名/节点时自动恢复正确配置 - 增加定时轮询机制,每100ms校验一次播放器状态,强制同步覆盖层显示逻辑
- 可对核心JS代码做混淆处理,提高用户定位核心逻辑的成本
修改后完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="css/bootstrap.min.css"> <link rel="stylesheet" href="css/styles.css"> <link rel="shortcut icon" href="imgs/icon/favicon.ico"> <style> .hytPlayerWrap { display: inline-block; position: relative; background-position: center; background-repeat: no-repeat; } .ytp-copylink-title{ display: none; } </style> <title> 2021</title> </head> <body id="plenario"> <div class="container-fluid"> <div class="row"> <div class="col-12"> <br><br><br><br> <div class="row"> <div class="col-2"> </div> <div class="col-8 text-center"> <div class="hytPlayerWrapOuter" > <div class="hytPlayerWrap" style="background-image:url(imgs/Captura.jpg)"> <iframe width="640" height="360" src="https://www.youtube-nocookie.com/embed/wzWmZYi4qMg?rel=0&controls=0&enablejsapi=1" allowfullscreen="allowfullscreen" frameborder="0"></iframe> </div> </div> </div> <div class="col-2"> </div> </div> </div> <div class="seccion-regresar-plenario"> </div> </div> </div> <script src="js/jquery-3.5.1.min.js"></script> <script src="js/bootstrap.bundle.min.js"></script> <script src="js/utiles.js"></script> <script> "use strict"; document.addEventListener('DOMContentLoaded', function () { if (window.hideYTActivated) return; // 覆盖层样式配置,不写入静态CSS const coverStyle = { ended: { content: '""', position: 'absolute', top: 0, left: 0, bottom: 0, right: 0, cursor: 'pointer', backgroundRepeat: 'no-repeat', backgroundPosition: 'center', backgroundSize: '64px 64px', backgroundImage: 'url(data:image/svg+xml;utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgNTEwIDUxMCI+PHBhdGggZD0iTTI1NSAxMDJWMEwxMjcuNSAxMjcuNSAyNTUgMjU1VjE1M2M4NC4xNSAwIDE1MyA2OC44NSAxNTMgMTUzcy02OC44NSAxNTMtMTUzIDE1My0xNTMtNjguODUtMTUzLTE1M0g1MWMwIDExMi4yIDkxLjggMjA0IDIwNCAyMDRzMjA0LTkxLjggMjA0LTIwNC05MS44LTIwNC0yMDQtMjA0eiIgZmlsbD0iI0ZGRiIvPjwvc3ZnPg==)' }, paused: { content: '""', position: 'absolute', left: 0, right: 0, width: '640px', height: '340px', cursor: 'pointer', backgroundRepeat: 'no-repeat', backgroundPosition: 'center', backgroundSize: '40px 40px', backgroundImage: 'url(data:image/svg+xml;utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEiIHdpZHRoPSIxNzA2LjY2NyIgaGVpZ2h0PSIxNzA2LjY2NyIgdmlld0JveD0iMCAwIDEyODAgMTI4MCI+PHBhdGggZD0iTTE1Ny42MzUgMi45ODRMMTI2MC45NzkgNjQwIDE1Ny42MzUgMTI3Ny4wMTZ6IiBmaWxsPSIjZmZmIi8+PC9zdmc+)' } } let onYouTubeIframeAPIReadyCallbacks = []; for (let playerWrap of document.querySelectorAll(".hytPlayerWrap")) { let playerFrame = playerWrap.querySelector("iframe"); let tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; let firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); let player; // 状态同步函数 const syncState = () => { if(!player) return const state = player.getPlayerState() // 清空之前的伪类样式 playerWrap.style.content = '' Object.keys(coverStyle.ended).forEach(k => playerWrap.style[k] = '') Object.keys(coverStyle.paused).forEach(k => playerWrap.style[k] = '') if(state === YT.PlayerState.ENDED){ Object.assign(playerWrap.style, coverStyle.ended) playerFrame.style.visibility = 'hidden' }else if(state === YT.PlayerState.PAUSED){ Object.assign(playerWrap.style, coverStyle.paused) playerFrame.style.visibility = 'hidden' }else if(state === YT.PlayerState.PLAYING){ playerFrame.style.visibility = 'visible' } } let onPlayerStateChange = function (event) { syncState() }; onYouTubeIframeAPIReadyCallbacks.push(function () { player = new YT.Player(playerFrame, {events: {'onStateChange': onPlayerStateChange}}); // 每100ms轮询同步状态 setInterval(syncState, 100) }); // 监听DOM变动,用户修改样式自动恢复 const observer = new MutationObserver(syncState) observer.observe(playerWrap, { attributes: true, childList: true, subtree: true, attributeFilter: ['style', 'class'] }) observer.observe(playerFrame, { attributes: true, attributeFilter: ['style', 'class'] }) playerWrap.addEventListener("click", function () { let playerState = player.getPlayerState(); if (playerState == YT.PlayerState.ENDED) { player.seekTo(0); } else if (playerState == YT.PlayerState.PAUSED) { player.playVideo(); } }); } window.onYouTubeIframeAPIReady = function () { for (let callback of onYouTubeIframeAPIReadyCallbacks) { callback(); } }; window.hideYTActivated = true; // 可选:禁用F12、右键等快捷操作,提高门槛 document.addEventListener('contextmenu', e => e.preventDefault()) document.addEventListener('keydown', e => { if(e.key === 'F12' || (e.ctrlKey && e.shiftKey && e.key === 'I')) e.preventDefault() }) }); </script> </body> </html>
额外强化建议
你可以将<script>标签内的核心逻辑通过JS混淆工具做混淆处理,替换所有可读变量名为无意义字符、加密字符串常量,进一步提高用户破解的成本。
内容的提问来源于stack exchange,提问作者Luis Alberto
相关产品推荐
相关产品推荐

