搜尋此網誌

2023年7月6日 星期四

對 iframe 鎖右鍵 ?

緣起:


    好一段時間沒寫文章了,之前大部份的時間都在寫私人的日記,不久前寫到煩躁了,所以就先停更一段時間。工作上的話,每天做的事情其實沒差很多,copy 現有的程式碼然後做一點小改動,之後就看有什麼問題再修。說實在的,沒學到什麼比較有技術的東西,但也沒什麼興致看我們專案比較難的部份就是。

    昨天,我們 PM 請我研究個東西,就是看能不能寫個 Script 來鎖定網站上的 iframe,讓右鍵點擊它們時會沒有作用,當作是一個簡單的防盜機制。

    先說結論,這無法做到,PM 在請教了我們資深的工程師後,得到的回答也是做不到,所以就請我不用再研究了。但在放棄前,我有試著想了一些旁門左道的方法來達成鎖定右鍵的功能,雖然最後是以失敗告終,但在這過程中有學到不少東西,所以想寫個文章記錄下來。


關於 iframe:


    有去查怎麼用 jquery 存取 iframe 裡的東西,查的過程中,有學到 X-Frame-Options 這東西,那些大網站的 http response header 都會加它,防止被 clickjack。

    再來是用 jquery 存取 iframe,就我的認知,iframe 裡的內容是禁止存取的,除非那個 iframe 跟目前的 html 文件是同源。

    我用簡單的程式碼 try 了一下,iframe 是複製 youtube 的內嵌分享。

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>iframe</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>

</head>
<body>
	<script>
		$(function(){
			$('iframe').each(function(index, elem){
				console.info($(this).contents());
			});
		})
	</script>
	<iframe width="560" height="315" src="https://www.youtube.com/embed/uuB-emHooIQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</body>
</html>


    確實能取得 iframe。


Top-Layer:


    後來是有成功弄個 div 出來擋住 iframe 啦,但不久後又意識到有另一個問題的存在,那就是全螢幕。我發現,影片使用全螢幕後,會出現一個 #top-layer 的區塊


    這東西會在網頁的 document 之上,而且長跟寬會佔滿你的螢幕,裡面放的即是我們的 iframe 元素。有些 dom 元素能用 requestFullScreen 的方法來讓自己變成全螢幕。

    如果我想要讓 iframe 在變全螢幕後也不能被點選,那我就要在那個 iframe 進入 #top-layer 時,用 div 把它給包起來。後來看到,document 有個 onfullscreenchange 的事件,當有東西進入 #top-layer 時就會被觸發,我們可以在 callback function 裡用 document.fullscreenElement 來取得目前在 #top-layer 的 dom,如果沒的話,它會是 null。

    我後來是沒有接著做幫進入 #top-layer 的 dom 包一個 div 的工作。


CSS 的 z-index:


    我想覆蓋 iframe,但不想動到它本身跟它周圍 dom 的排列與顯示,所以在 css 上要知道怎麼用一個 div,剛好把 iframe 給蓋住。最先想到要調整的就是 div 的 z-index,把它調大一點才能,蓋過 iframe,不過,我後來看到這文章 ,它最後有提到,如果我那個當遮罩用的 div,它的父層跟 iframe 不一樣,有可能調了 zindex 後,還是不能擋住 iframe。

    所以我就想到了一個架構,就是先用一個 div 把 iframe 給包住,之後再把當遮罩用的 div 給放到裡面,這樣,遮罩 div 就會跟 iframe 在同一個階層了。


jquery 的 wrap:


    這邊開始實做,用 jquery 的 $('<div></div>') 可以弄出一個 div 的 jquery instance,jquery 的 wrap 可以把一個 html 元件用另一個 html 元件給包起來,beforeafter 則可以把 html 元素加在目標物前面或後面

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>iframe</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
</head>
<body>
	<script>
		$(function(){
			$('iframe').each(function(index, elem){
                
                let $wrapDiv = $('<div></div>');
                let $blockDiv=$('<div></div>')
                $(elem).wrap($wrapDiv);
                $(elem).after($blockDiv);
			});
		})
	</script>
	<iframe width="560" height="315" src="https://www.youtube.com/embed/uuB-emHooIQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</body>
</html>

結果

    可以看到,iframe 有被 div 包著了,而且在它下方也多了一個 div。


CSS 的調整:



    div 預設的 display 是 block,這不是我想要的,所以我就去查 display,這東西我不是很熟,也不會介紹,但經過我的嘗試,發現把 display 設成 inline-block 可以達成我的需求。設成 inline-block 後,div 的大小就會貼齊子元素。

    接著是關於 position,我是看這篇文章學習的,要注意的是,最外層 div 的 postion 要設成 relative,這樣裡面的那個當遮罩用的 div,在 postion 設成 absolute 時,它在向上找定位點時才不會找到 body 去。再來把遮罩 div 的長跟寛都設成 100%,它就會貼齊最外層,最後再給它的 zindex 一個比較大的數字,就差不多完成了。

    程式碼如下
<html lang="en"$gt;

<head$gt;
    <meta charset="UTF-8"$gt;
    <title$gt;iframe</title$gt;
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"$gt;</script$gt;
</head$gt;

<body$gt;
    <script$gt;
        $(function () {
            $('iframe').each(function (index, elem) {
                let $wrapDiv = $('<div$gt;</div$gt;');
                let $blockDiv = $('<div$gt;</div$gt;');
                
                $wrapDiv.css('display', 'inline-block');
                $wrapDiv.css('position', 'relative');
                $blockDiv.css('height', '100%');
                $blockDiv.css('width', '100%');
                $blockDiv.css('position', 'absolute');
                $blockDiv.css('top', '0px');
                $blockDiv.css('left', '0px');
                $blockDiv.css('z-index', '1000');

                $(elem).wrap($wrapDiv);
                $(elem).after($blockDiv);
            });
        })
    </script$gt;

    <iframe width="560" height="315" src="https://www.youtube.com/embed/uuB-emHooIQ" title="YouTube video player"
        frameborder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
        allowfullscreen$gt;</iframe$gt;
</body$gt;

</html$gt;

    可以看到,遮罩的 div 確實有擋住 iframe,不過這樣就不光是鎖右鍵了,我們根本碰不著 iframe 裡的東西 XD

    就只能先這樣了,至少,我學到不少好用的東西。



沒有留言:

張貼留言