<!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小时内与您取得联系。