今天来学习下CSP(内容安全策略)

718 阅读3分钟

这是我参与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
*通配符,代表所有
hashhash值是根据标签的内容使用hash算法生成hash值(不包含标签)
nonce值(nonce-xxx)xxx是你自己定义的,然后在使用的标签上带有这个属性和值

'unsafe-inline'一般是配合style-srcscript-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域名的资源

所以控制台报错了,如下

image.png

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>

本地运行,效果如下:

image.png

总结

以上就是我总结的CSP(内容安全策略),它支持的属性是比较多的,大家都可以复制代码去试试。

感谢你们的阅读。