这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战
前言
昨天讲了如何限制网站不能被iframe嵌套,里面有一种方式是设置CSP(内容安全策略),它不单单只是可以限制网站被iframe嵌套,还有别的用法,今天来讲讲它。
CSP(内容安全策略)
CSP,内容安全策略,全称是Content-Security-Policy
,主要是允许网页加载的哪些资源,不符合这些策略的资源无法加载,一定程度上可以防范XSS的攻击。
语法
Content-Security-Policy: 指令 指令值,指令值; 指令 指令值,指令值...
对应的指令有以下这些:
指令 | 描述 |
---|---|
default-src | 设置所有加载资源的默认策略,当其它指令没设置时,就会走默认策略 |
script-src | 设置script标签加载资源的策略 |
style-src | 设置style标签加载样式的策略 |
font-src | 设置font标签加载字体的策略 |
img-src | 设置img标签加载图片的策略 |
media-src | 设置视频或者音频文件加载的策略 |
frame-ancestors | 设置本页面是否能够被ifame嵌套的策略 |
frame-src | 设置本页面是否能够加载ifame标签的策略(旧) |
child-src | 设置本页面是否能够加载ifame标签的策略(新) |
object-src | 设置flash插件加载的策略 |
connect-src | 设置http请求的策略 |
base-uri | 设置base元素url的策略 |
form-action | 设置表单提交url的策略 |
report-uri | 设置上报uri的策略 |
对应的指令值有以下值:
指令值 | 描述 |
---|---|
'none' | 不允许加载任何资源(注意是带引号的,下同) |
'self' | 加载同源资源 |
'unsafe-inline' | 加载内联样式(style,script等) |
'unsafe-eval' | 加载eval函数的代码 |
http: | 加载http协议的资源 |
https: | 加载https协议的资源 |
data: | 加载data协议(比如base64地址开头就是data)的资源 |
域名 | 加载该域名下的资源 比如aaa.com |
路径 | 加载该路径下的资源 比如aaa.com/js |
* | 通配符,代表所有 |
hash 值 | hash值是根据标签的内容使用hash算法生成hash值(不包含标签) |
nonce 值(nonce-xxx) | xxx是你自己定义的,然后在使用的标签上带有这个属性和值 |
'unsafe-inline'
一般是配合style-src
和script-src
一切使用,如果使用了'unsafe-inline'
值,需要提供hash
值或者nonce
值
hash
值的例子如下:(这个hash值是根据你使用的标签的内容用hash算法生成的,我这里使用了script-src, 我是把script的内容生成的)
"Content-Security-Policy": "script-src 'self' test.com 'sha256-SSgNhkZfi99ERRqGlhN+DPzGVQweujriyBN2iwMtE+k='"
nonce
值的例子如下:
"Content-Security-Policy": "script-src 'self' test.com 'nonce-test'"
在script标签使用
<script nonce="test">
alert('hello world!')
</script>
设置方式
设置CSP有两种方式,请求头上http header
设置和meta
标签设置。
http header
设置
新建一个页面 index.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>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
<div>你好,我是cp3!</div>
</body>
</html>
新增index.js
const http = require('http')
const fs = require('fs')
http.createServer((req, res) => {
fs.readFile('./index.html', (err, data) => {
res.writeHead(200, {
'Content-Type': 'text/html; charset=UTF-8',
"Content-Security-Policy": "script-src 'self' test.com"
})
res.write(data)
res.end()
})
}).listen(8081)
console.log('服务已开启,请打开http://127.0.0.1:8081')
node执行index.js
因为我加载了一个cdn的jquery文件,然后我csp
设置了 "script-src 'self' test.com"
,只允许加载同源资源和test.com域名的资源
所以控制台报错了,如下
meta标签
设置
上面的效果也可以通过设置meta
来实现:
<!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">
<!-- csp meta标签 -->
<meta http-equiv="Content-Security-Policy" content="script-src 'self' test.com">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
<div>你好,我是cp3!</div>
</body>
</html>
本地运行,效果如下:
总结
以上就是我总结的CSP(内容安全策略),它支持的属性是比较多的,大家都可以复制代码去试试。
感谢你们的阅读。