# 内容安全策略

# 作用

  • 限制资源获取
  • 报告资源获取越权

# 限制方式

  • default-src 限制全局:限制所有跟链接请求有关的作用范围;
  • 指定资源类型

# node 实践

# 限制资源的加载只能通过 http/https 的方式

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/') {
    const html = fs.readFileSync('test.html', 'utf-8')
    res.writeHead(200, {
      'Content-Type': 'text/html',
      // 限制 html 中只能通过 http 或者 https 的方式请求资源,内联的方式不行; 会报错:Refused to execute inline script 
      'Content-Security-Policy': 'default-src http: https:'
    })
    res.end(html)
  }
}).listen(8888)

# 限制只能加载本域名下的资源

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/') {
    const html = fs.readFileSync('test.html', 'utf-8')
    res.writeHead(200, {
      'Content-Type': 'text/html',
      'Content-Security-Policy': 'default-src \'self\''
    })
    res.end(html)
  }
}).listen(8888)

# 限制可以在指定域名下加载资源

允许 https://cdn.bootcss.com/ 域名下的资源可以加载

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/') {
    const html = fs.readFileSync('test.html', 'utf-8')
    res.writeHead(200, {
      'Content-Type': 'text/html',
      'Content-Security-Policy': 'default-src \'self\' https://cdn.bootcss.com/'
    })
    res.end(html)
  }
}).listen(8888)

# 限制表单提交到本域名地址

form-action 'self' 限制提交的范围

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/') {
    const html = fs.readFileSync('test.html', 'utf-8')
    res.writeHead(200, {
      'Content-Type': 'text/html',
      'Content-Security-Policy': 'default-src \'self\'; form-action \'self\''
    })
    res.end(html)
  }
}).listen(8888)

# 不对全局资源请求限制,只限制 script 资源请求

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/') {
    const html = fs.readFileSync('test.html', 'utf-8')
    res.writeHead(200, {
      'Content-Type': 'text/html',
      'Content-Security-Policy': 'script-src \'self\''
    })
    res.end(html)
  }
}).listen(8888)

# 发送发生违规的文档 URI

如果我们对页面资源请求做了限制,但发生了违规,可以将违规信息发送到服务器: report-uri /report 后面的 /report 是发送违规文档的 url 地址。

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/') {
    const html = fs.readFileSync('test.html', 'utf-8')
    res.writeHead(200, {
      'Content-Type': 'text/html',
      'Content-Security-Policy': 'script-src \'self\'; form-action \'self\'; report-uri /report'
    })
    res.end(html)
  }
}).listen(8888)

# 不限制文件违规不加载,只限制发送违规的文档

修改 Content-Security-Policy-Report-Only 为头信息。

const http = require('http')
const fs = require('fs')
http.createServer(function(req, res) {
  if (req.url === '/') {
    const html = fs.readFileSync('test.html', 'utf-8')
    res.writeHead(200, {
      'Content-Type': 'text/html',
      'Content-Security-Policy-Report-Only': 'script-src \'self\'; form-action \'self\'; report-uri /report'
    })
    res.end(html)
  }
}).listen(8888)

# html 中使用 meta 标签进行内容安全策略限制

report-uri 是不能在 meta 中设置

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- report-uri 是不能在 meta 中设置 -->
  <meta http-equiv="Content-Security-Policy" content="script-src 'self'; form-action 'self'">
  <!-- connect-src 是限制发送 ajax 请求 -->
  <!-- <meta http-equiv="Content-Security-Policy" content="connect-src 'self'; form-action 'self'"> -->
</head>

评 论:

更新: 11/21/2020, 7:00:56 PM