<!DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript"> //這里可以寫js代碼了 </script> </body> </html>
2. 創建js文件與html文件分離:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript" src='script.js'></script> </body> </html>
然后就可以在script.js中寫js代碼了。
js輸出語句比較多,比如document.write、console.log等。
1.document.write:在頁面中輸出文本內容。
代碼:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript"> document.write("輸出文本內容了") </script> </body> </html>
效果圖:
2.console.log:在控制臺輸出內容。
代碼:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript"> console.log("輸出文本內容"); </script> </body> </html>
效果圖:
console是在控制臺中顯示,在瀏覽器右擊有一個審查元素(或者F12),就可以看到Console這個內容了。
文地址:Script Integrity[1]
原文作者:Chris Coyier[2]
最近有很多關于 polyfill.io 的新聞。幾年前,這個項目很熱門,因為你只需引用它,它就會根據瀏覽器 UA 及其 API 特性支持情況,自動為你添加相對應的 polyfill。現在如果你按他們官網主頁的建議,從他們的域名加載了腳本,你的網頁可能會被注入一些惡意代碼。
安全漏洞情報公司說,惡意代碼可能是基于用戶當前位置,然后把他們重定向到體育博彩網站或成人域名。 SecurityWeek[3]
該項目現已下線,但截至 2024 年 6 月 1 日,他們建議采用這種直接鏈接的方式加載腳本。
當你加載一個你無法控制的域名上的任何資源時,這就是一種風險。這是一種可預期的風險,例如,很多網站都會從 google.com 上加載腳本,用于 Google Analytics;或者從 adobe.com 上下載字體用于排版。這些都是值得信任的資源,但這種信任完全取決于你。
web 中有個屬性可以防止第三方更改他們提供的代碼。這就是 <script> 或 <link> 標簽(rel="stylesheet", rel="preload" 或 rel="modulepreload")上的 integrity 屬性[4]。完整的名稱是“子資源完整性”。
舉個例子:
<script
src="https://third-party.com/script.js"
integrity="sha384-[hash value here]">
</script>
現在,如果 script.js 有任何變化,哪怕只是一個字符,瀏覽器都會拒絕執行腳本(或樣式表)。非常安全!
一些負責任的第三方會直接提供這一功能,這一點很好。
instant.page 提供的腳本,并提供完整性屬性以確保安全。
CDNjs 會將 integrity 屬性作為你復制和粘貼時默認代碼的一部分。
我特別喜歡完整性提供的保護,它還能防止一些可能的中間人攻擊。如果你的酒店 WiFi 不正規,它會攔截請求并更改響應(我見過!),完整性驗證就會阻止被篡改的腳本執行。除非他們也篡改 HTML 并更改屬性值,這當然是有可能的,因為更改 HTML 正是侵入式應用所做的事情。不過,大多數安全措施都是 “能做多少就做多少”,這樣做還是有幫助的。
上述兩個例子的腳本鏈接地址比較好,因為它們的地址都是有版本控制的。它們發布的是確切的版本,而且該版本永遠不會更改。這是開源社區的版本管理約定,當公共庫發布后,該版本的代碼就會被鎖定,任何更改都需要升級版本。如果代碼在沒有版本更新的情況下發生了變化,那將是非常可疑的,很可能是惡意的,也是使用 <script integrity="..."> 的最佳情況。此外,發布庫的主要倉庫(如 npm)無論如何都不允許更改已發布版本的代碼。
雖然腳本完整性通常是一個很好的方案,但它是專門用于不會改變的版本化資源。如果出現以下情況,就不能使用它:
也許你正在使用某個分析服務提供商提供的腳本。他們在給你提供腳本時,很可能不會使用 integrity 屬性。這很可能是因為他們希望能夠積極開發該腳本及其功能,而不必告訴每一位客戶他們需要更新腳本的版本,否則腳本就會停止工作。
具有諷刺意味的是,公司能夠即時更新腳本意味著他們有可能修補安全問題。
也許可以,這取決于攻擊者做了什么。有些報道[5]是這么說的:
惡意代碼根據 HTTP 請求頭動態生成響應內容,如僅在特定移動設備上激活,從而躲避檢測、避開管理員用戶并延遲執行,同時代碼還被混淆。
所以如果腳本出現了問題,它的響應內容與創建完整性值時的內容不同,那么瀏覽器就會阻止這些惡意更改的運行。
但它們也可能躲過這種阻止。
polyfill.io 的工作方式是根據需要去加載附加內容(即 polyfill 本身)。這些額外加載的內容可以被改成惡意內容,而且不會受到子資源完整性的限制。我并不想讓壞人活得更輕松,只是說說而已。
你不用一定要求第三方庫提供此屬性來給你使用,這只是 web 的一項功能,你想用就用。
也許更簡單的方法是訪問 SRI 哈希值生成器網站,輸入要保護的資源的 URL,然后點擊按鈕獲取代碼:
注意:我看到很多地方推薦這個網站,但當我使用時,它似乎并不適合我。例如,上面的代碼:
<script src="https://assets.codepen.io/3/log-something.js" integrity="sha384-ZTxYWn5UcuOi7Xt1wWg/QFcsZJEXjJg7tgCnVbx0+ssBvbi1Sw/hY5GzPGHSD1NW" crossorigin="anonymous"></script>
在 Chrome 瀏覽器中打開,我的 integrity 屬性并不對。我不得不讓 Chrome 瀏覽器在控制臺中顯示錯誤信息,并尋找錯誤信息中提供正確的哈希值,然后使用修正后的哈希值才能正常工作:
<script src="https://assets.codepen.io/3/log-something.js" integrity="sha384-H7W+IxM2qbwMSJYRqmcgYXq0TRko/BIFtURUjh2QG0Z8MM9I6t2f4n+2BOCmbjvD" crossorigin="anonymous"></script>
所以,你的情況可能會有所不同。這里有個代碼演示地址[6]。
值得注意的是,其中還涉及 CORS。如果沒有 crossorigin="anonymous",上面的代碼中就會看到了 CORS 錯誤,盡管我們在提供資源時使用了 Access-Control-Allow-Origin: * 響應頭。聳聳肩 - 網站很難做。
[1] Script Integrity: https://frontendmasters.com/blog/script-integrity/
[2] Chris Coyier: https://frontendmasters.com/blog/author/chriscoyier/
[3] SecurityWeek: https://www.securityweek.com/polyfill-supply-chain-attack-hits-over-100k-websites/
[4] integrity 屬性: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
[5] 有些報道: https://cside.dev/blog/more-than-100k-websites-targeted-in-web-supply-chain-attack
[6] 代碼演示地址: https://codepen.io/chriscoyier/pen/qBzWMxQ?editors=1000
明:文章內容僅用于學習交流,切勿不當使用。
上網的時候經常會遇到網頁禁止復制文本或者禁止文檔下載的情況。今天結合案例分析下實現這些限制的手法和解除辦法。
首先創建一個demo.html的文檔,文檔內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DEMO</title>
<style>
body {background-color: aqua;}
</style>
</head>
<body>
<div class="content">測試文本測試文本測試文本</div>
<script>
let htmlEle=document.documentElement;
let bodyEle=document.querySelector('body');
htmlEle.addEventListener('selectstart', (e)=> {
e.preventDefault();
});
bodyEle.addEventListener('copy', (e)=> {
e.preventDefault();
});
bodyEle.addEventListener('selectstart', (e)=> {
e.preventDefault();
});
bodyEle.addEventListener('contextmenu', (e)=> {
e.preventDefault();
});
</script>
</body>
</html>
打開文檔可以發現,頁面文本是無法選擇并復制的。因為如代碼所示,頁面元素被綁定了幾個事件(選擇、拷貝、右鍵菜單),阻止了用戶對文本的復制企圖。
怎么辦呢?
打開瀏覽器的開發者工具,切換到Elements標簽下,選擇文本元素,這時可以在下方的“事件監聽器”中查看到目標元素及其祖先元素上綁定的事件。展開這些相關的事件,可以看到“移除”按鈕,接下來只需點擊按鈕將這些限制事件移除便可以復制了。
上述辦法是在事件綁定后,再將它們移除。此外,也可以通過抓包改包的方式移除綁定事件相關的代碼,從源頭阻止事件的綁定。這需要抓包工具的輔助,這里用到的是Fiddler。
假設網頁部署在本地服務器上,首先,打開Fiddler,在右側切換到“自動轉發”面板(帶閃電圖標的),勾選圖中兩個選項;然后添加規則,填上要更改的請求地址以及要替換的本地文件(假設為demo1文件,內容如下),填好后保存。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DEMO</title>
<style>
body {background-color: #dedede;}
</style>
</head>
<body>
<div class="content">測試文本測試文本測試文本</div>
</body>
</html>
設置好以后再次刷新網頁,會發現頁面的背景色發生了變化,而且文本也可以直接復制了。
此處以網上的一個文檔為例,文檔可以在線查看,但是無法直接下載。通過開發者工具選中文檔,可以看到它對應了一個img標簽(以前是canvas),我們可以將圖片保存到本地,但是如果頁面比較多,手動操作就很麻煩,所以可以用代碼幫我們自動執行,將圖片合并成pdf文件并下載到本地。
以下代碼可做參考:
function loadScript (url) {
let ele=document.createElement('script')
ele.src=url
document.body.appendChild(ele)
}
function img2dataUrl (options) {
let result=''
let img=options.img || ''
let width=options.width || img.naturalWidth || img.clientWidth
let height=options.height || img.naturalHeight || img.clientHeight
let quality=options.quality || 100
let mimeType=options.mimeType || 'image/png'
let canvas=document.createElement('canvas')
canvas.width=width
canvas.height=height
let ctx=canvas.getContext('2d')
ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, width, height)
result=canvas.toDataURL(mimeType, quality / 100)
return result
}
loadScript('https://cdn.bootcdn.net/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js')
function img2pdf () {
let imgArr=[...document.querySelectorAll('.reader_inner img')]
if (imgArr.length===0) return
let doc=new jspdf.jsPDF({unit:'px'});
imgArr.forEach((v,i)=> {
v.setAttribute("crossOrigin",'anonymous');
let pxPermm=v.width / 210 / 2.2;
let imgData=img2dataUrl({img:v}).slice('data:image/png;base64,'.length);
(i > 0) && doc.addPage();
doc.addImage(imgData, 'png', 0, 0, v.width / pxPermm, v.height / pxPermm);
})
doc.save('img2pdf.pdf');
}
將代碼放到控制臺或者代碼段中執行,執行后,再在控制臺調用 img2pdf() 方法即可將可瀏覽的頁面合并成PDF下載到本地。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。