Có nhiều cách không an toàn để liệt kê danh sách trắng các thẻ tập lệnh nội tuyến, trình xử lý sự kiện nội tuyến, thẻ kiểu nội tuyến và kiểu nội tuyến, nhưng tôi sẽ không nói về chúng vì chúng không an toàn và phá vỡ toàn bộ quan điểm của CSP Đặt CSP trong Nút. jsĐể xác định tài nguyên được phép trong CSP thông qua Nút. js, chúng ta phải khai báo chúng dưới dạng tiêu đề phản hồi - Người dùng đưa ra yêu cầu
- Máy chủ gửi phản hồi
- Trình duyệt tải trang cùng với các tài nguyên được phép
CSP nằm trong tiêu đề phản hồi và nơi trình duyệt sẽ xem để biết anh ta có thể hiển thị những gì Sử dụng Express, chúng ta chỉ cần làm như sau
// /index.js
const express = require("express")
const app = express()
// Set CSP as a middleware function
app.use(function (req, res, next) {
res.setHeader(
"Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'"
)
next()
})
app.get("/", (req, res) => {
res.send("Hello World!")
})
app.listen(3000, () => {
console.log(`App 🚀 @ http://localhost:3000`)
})
Vào chế độ toàn màn hình Thoát chế độ toàn màn hình Như bạn có thể thấy, chúng tôi đã xác định các lệnh được sử dụng nhiều nhất cho // Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
4, nghĩa là chúng tôi chỉ cho phép các tài nguyên từ máy chủ hiện tại (bao gồm lược đồ URL và số cổng) mà thôi.
Nếu bạn chạy ứng dụng này (// Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
5) và theo liên kết, bạn sẽ nhận được một Hello World đẹp mắt
Nếu bạn mở Bảng điều khiển (F12), bạn sẽ không thấy gì vì hiện tại chúng tôi chưa làm gì nhiềuEJSĐể hiển thị trang // Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
6, hãy tải các tập lệnh và kiểu bên ngoài để kiểm tra CSP của chúng tôi, tôi sẽ sử dụng EJS
Vui lòng sử dụng bất kỳ công cụ mẫu nào khác phù hợp với nhu cầu của bạn
Tôi đánh giá cao EJS vì lý do sauEJS là một ngôn ngữ tạo khuôn mẫu đơn giản cho phép bạn tạo đánh dấu HTML bằng JavaScript đơn giản
Sau khi cài đặt EJS ( // Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
7), chúng ta sẽ phải tạo một thư mục // Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
8, ở thư mục gốc của ứng dụng, để lưu trữ các tệp // Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
9
EJS sẽ xem bên trong thư mục này để document.getElementById("my-div").setAttribute("style", "background-color:red;")
0 (các) trang của bạn theo cách bạn hướng dẫn anh ấy thực hiện Trong thư mục này, tạo một tệp tên là document.getElementById("my-div").setAttribute("style", "background-color:red;")
1 với nội dung sau
<!-- /views/index.ejs -->
<!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>
</head>
<body>
<h1>Hello from EJS !</h1>
</body>
</html>
Vào chế độ toàn màn hình Thoát chế độ toàn màn hình Có, tệp // Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
9 là tệp // Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
6 trong đó chúng tôi có thể sử dụng document.getElementById("my-div").setAttribute("style", "background-color:red;")
4 đơn giản, chúng tôi sẽ thấy điều đó trong giây látCập nhật tệp máy chủ chính của chúng tôi để trông như thế này
// /index.js
const express = require("express")
const app = express()
// Set CSP as a middleware function
app.use(function (req, res, next) {
res.setHeader(
"Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'"
)
next()
})
// Set EJS as a template engine
app.set("view engine", "ejs")
// Use EJS to render our page(s)
app.get("/", (req, res) => {
res.render("index") // renders index.ejs
})
app.listen(3000, () => {
console.log(`App 🚀 @ http://localhost:3000`)
})
Vào chế độ toàn màn hình Thoát chế độ toàn màn hình nguồn lực bên ngoàiBây giờ, để kiểm tra CSP của chúng tôi, chúng tôi chỉ cần tải một số tài nguyên bên ngoài
Hãy mang về Pure. css và Lodash Cập nhật document.getElementById("my-div").setAttribute("style", "background-color:red;")
1 để trông như thế này
<!-- /views/index.ejs -->
<!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>
<!-- Pure.css -->
<link
rel="stylesheet"
href="https://unpkg.com/[email protected]/build/pure-min.css"
integrity="sha384-yHIFVG6ClnONEA5yB5DJXfW2/KC173DIQrYoZMEtBvGzmf0PKiGyNEqe9N6BNDBH"
crossorigin="anonymous"
/>
</head>
<body>
<h1>Hello from EJS !</h1>
<!-- Lodash -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
</body>
</html>
Vào chế độ toàn màn hình Thoát chế độ toàn màn hình Lưu document.getElementById("my-div").setAttribute("style", "background-color:red;")
1, tải lại ứng dụng trong trình duyệt và mở Bảng điều khiển
// Firefox Console
⚠️ Loading failed for the <script> with source “https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js”.
🛑 Content Security Policy: The page’s settings blocked the loading of a resource at https://unpkg.com/[email protected]/build/pure-min.css (“style-src”).
🛑 Content Security Policy: The page’s settings blocked the loading of a resource at https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js (“script-src”).
Vào chế độ toàn màn hình Thoát chế độ toàn màn hình <button id="btn" onclick="doSomething()"></button>
0Vào chế độ toàn màn hình Thoát chế độ toàn màn hình Bây giờ, bạn có thể thấy rằng CSP của chúng tôi đã chặn Pure. css và Lodash, vì vậy mọi thứ đang hoạt động như mong đợi vì chúng không được định nghĩa trong CSP của chúng tôi là tài nguyên được phép tải trong trình duyệt Mũ bảo hiểmHãy tưởng tượng, không nhất thiết là vì nó xảy ra khi bạn đang tạo một ứng dụng, có một số lượng tập lệnh và kiểu hợp lý để đưa vào danh sách trắng
Chức năng phần mềm trung gian CSP trong tệp máy chủ chính sẽ phát triển và trở nên xấu xí và khó bảo trì
Một giải pháp thay thế tuyệt vời là sử dụng Mũ bảo hiểm nếu bạn đang sử dụng Express Mũ bảo hiểm giúp bạn bảo mật các ứng dụng Express của mình bằng cách đặt các tiêu đề HTTP khác nhau
Hãy thêm Mũ bảo hiểm vào ứng dụng Express của chúng tôi bằng lệnh sau document.getElementById("my-div").setAttribute("style", "background-color:red;")
7
Để dễ dàng duy trì CSP của chúng ta, hãy di chuyển nó vào trong thư mục document.getElementById("my-div").setAttribute("style", "background-color:red;")
8, thư mục gốc của ứng dụng, trong một tệp có tên document.getElementById("my-div").setAttribute("style", "background-color:red;")
9
Cấu trúc ứng dụng trông giống như cây sau
<button id="btn" onclick="doSomething()"></button>
1Vào chế độ toàn màn hình Thoát chế độ toàn màn hình Hãy thêm một CSP với Mũ bảo hiểm
<button id="btn" onclick="doSomething()"></button>
2Vào chế độ toàn màn hình Thoát chế độ toàn màn hình và cập nhật document.getElementById("my-div").style.backgroundColor = "red"
0 để gọi phần mềm trung gian này
<button id="btn" onclick="doSomething()"></button>
3Vào chế độ toàn màn hình Thoát chế độ toàn màn hình Lưu cả hai tệp, làm mới trình duyệt của bạn và mở Bảng điều khiển
<button id="btn" onclick="doSomething()"></button>
4Vào chế độ toàn màn hình Thoát chế độ toàn màn hình <button id="btn" onclick="doSomething()"></button>
5Vào chế độ toàn màn hình Thoát chế độ toàn màn hình Như bạn có thể thấy, hiện chỉ có Lodash bị chặn 🤔 Và Firefox đang đưa ra cảnh báo cho một chỉ thị không xác định Về cơ bản, có rất nhiều điều đang xảy ra và sẽ có một loạt bài đăng để giải thích chi tiết từng tiêu đề và cách định cấu hình chúng Nhưng bạn biết đấy, Mũ bảo hiểm đặt một loạt các giá trị mặc định để bảo vệ điểm cuối của bạn một trong số đó là
document.getElementById("my-div").style.backgroundColor = "red"
1 Đây là chỉ thị cho phép Pure. css Nó có nghĩa là. "cho phép bất kỳ nguồn kiểu nào từ miền của tôi hoặc nguồn kiểu được cung cấp qua https hoặc kiểu nội tuyến" Nhưng như tôi đã nói trước đây, bất kỳ biểu thức document.getElementById("my-div").style.backgroundColor = "red"
2 nào đều không an toàn và không nên được sử dụng trừ khi chúng thực sự không còn lựa chọn nào khác
Tôi đã liên kết ở phần đầu của phần này với tài liệu của Mũ bảo hiểm Chúng tôi sẽ giải quyết tất cả các vấn đề một cách chính xác trong phần tiếp theo và phần cuối cùngHash và NonceĐể cho phép thực thi tập lệnh nội tuyến, trình xử lý sự kiện nội tuyến và kiểu nội tuyến, có thể chỉ định một hàm băm hoặc nonce khớp với mã nội tuyến, để tránh sử dụng biểu thức document.getElementById("my-div").style.backgroundColor = "red"
3Băm
Băm là một chuỗi bao gồm hai phần được kết nối bằng dấu gạch ngang với nhau - Thuật toán mật mã được sử dụng để tạo giá trị băm
- Hàm băm được mã hóa base64 của tập lệnh hoặc kiểu
CSP hỗ trợ sha256, sha384 và sha512 Nhưng khi bạn băm một tập lệnh hoặc một kiểu, chuỗi được tạo chỉ khớp với mã được băm, nghĩa là nếu mã thay đổi theo bất kỳ cách nào (dấu chấm, dấu cách, dòng mới, nhận xét, mã được thêm/xóa/định dạng) thì hàm băm sẽ không
Trong trường hợp này, bạn sẽ phải tạo lại một hàm băm phù hợp với mã đã sửa đổi
Đó là một quá trình tốn thời gian nếu mã của bạn thay đổi nhiều, nhưng thường được sử dụng và khuyên dùng hơn một lần, đặc biệt đối với các tập lệnh tĩnh từ MDN Ghi chú. Chỉ sử dụng nonce cho các trường hợp bạn không có cách nào khác bằng cách sử dụng nội dung kiểu hoặc tập lệnh nội tuyến không an toàn. Nếu bạn không cần nonce, đừng sử dụng nó. Nếu tập lệnh của bạn là tĩnh, bạn cũng có thể sử dụng hàm băm CSP để thay thế. (Xem ghi chú sử dụng trên. ) Luôn cố gắng tận dụng tối đa các biện pháp bảo vệ CSP và tránh các nonce hoặc tập lệnh nội tuyến không an toàn bất cứ khi nào có thể
nonce
Mặt khác, nonce là số mật mã được sử dụng một lần, được tạo bằng trình tạo số ngẫu nhiên bảo mật bằng mật mã, phải là duy nhất cho mỗi phản hồi HTTP dưới dạng chuỗi mã hóa base64 ngẫu nhiên gồm ít nhất 128 bit dữ liệu Vì vậy, trong trường hợp kết xuất phía máy chủ, một nonce thường được sử dụng hơn và có thể được sử dụng cho các tập lệnh và kiểu nội tuyến và bên ngoài
Lưu ý rằng một document.getElementById("my-div").style.backgroundColor = "red"
4 sẽ không cho phép các yêu cầu biểu định kiểu bắt nguồn từ quy tắc document.getElementById("my-div").style.backgroundColor = "red"
5Để sử dụng một nonce, cho một tập lệnh, chúng ta phải khai báo ở đầu chỉ thị // Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
1 biểu thức document.getElementById("my-div").style.backgroundColor = "red"
7 để cho phép thực thi tập lệnh đó cũng như bất kỳ tập lệnh nào được tải bởi tập lệnh gốc này
Khi sử dụng biểu thức document.getElementById("my-div").style.backgroundColor = "red"
7, các biểu thức khác như // Inline style tag gets ignored
<style>
#my-div {
background-color: red;
}
</style>
// Inline style attribute gets also ignored
<div id="my-div" style="background-color:red">I will not have a red background !</div>
4 hoặc document.getElementById("my-div").style.backgroundColor = "red"
3 sẽ bị bỏ quaTôi muốn giữ cho mã của mình sạch sẽ và có thể bảo trì được vì lúc này hay lúc khác tôi sẽ muốn cập nhật mã, đây là lý do tại sao tôi chia (như hầu hết các nhà phát triển) mã của mình thành các phần để mỗi phần có thể dễ dàng theo dõi trong tương lai gần hoặc xa. Hãy thêm một tệp có tên là // /index.js
const express = require("express")
const app = express()
// Set CSP as a middleware function
app.use(function (req, res, next) {
res.setHeader(
"Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'"
)
next()
})
app.get("/", (req, res) => {
res.send("Hello World!")
})
app.listen(3000, () => {
console.log(`App 🚀 @ http://localhost:3000`)
})
1 vào thư mục document.getElementById("my-div").setAttribute("style", "background-color:red;")
8, cấu trúc ứng dụng bây giờ trông giống như cái cây sau
<button id="btn" onclick="doSomething()"></button>
6Vào chế độ toàn màn hình Thoát chế độ toàn màn hình Mở // /index.js
const express = require("express")
const app = express()
// Set CSP as a middleware function
app.use(function (req, res, next) {
res.setHeader(
"Content-Security-Policy",
"default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'"
)
next()
})
app.get("/", (req, res) => {
res.send("Hello World!")
})
app.listen(3000, () => {
console.log(`App 🚀 @ http://localhost:3000`)
})
1 và thêm nội dung sau
<button id="btn" onclick="doSomething()"></button>
7Vào chế độ toàn màn hình Thoát chế độ toàn màn hình Mô-đun tiền điện tử là chức năng tích hợp sẵn của Node. js nhưng tốt hơn hết là kiểm tra xem nó có được bao gồm hay không, trong bản cài đặt của chúng tôi, giống như tài liệu
Làm cách nào để tạo nonce ngẫu nhiên trong JavaScript?
Trước tiên, chúng tôi xác định một chuỗi gồm tất cả các ký tự được phép trong chuỗi ngẫu nhiên cuối cùng của chúng tôi. Sau đó, chúng tôi lặp lại cho đến khi có độ dài nhất định sẽ đại diện cho kích thước chuỗi. Trong vòng lặp này, chúng ta sẽ xem xét chuỗi ký tự được phép dưới dạng một loại mảng (từng ký tự một) và chọn ngẫu nhiên một chỉ mục của mảng
Nonce trong Javascript là gì?
Thuộc tính toàn cục nonce là một thuộc tính nội dung xác định một nonce mật mã ("số được sử dụng một lần") có thể được Chính sách bảo mật nội dung sử dụng để xác định xem một lần tìm nạp nhất định có được phép tiến hành cho một phần tử nhất định hay không
Làm cách nào để tạo tên ngẫu nhiên trong JavaScript?
Mảng. áp dụng (null, Mảng (N)). bản đồ (hàm () { return s. charAt(Toán. tầng (Toán. ngẫu nhiên() * s. chiều dài)); . tham gia(''); . Toán học. ngẫu nhiên(). toString(36). lát(-5); . ngẫu nhiên() trả về 0. 0?. @ x-ray, bạn sẽ nhận được "0";). Chính xác. ;)
Làm cách nào để lấy chuỗi ngẫu nhiên từ mảng trong JavaScript?
Ví dụ. Lấy mục ngẫu nhiên từ một mảng . Một số ngẫu nhiên từ 0 đến mảng. chiều dài được tạo bằng Math. phương pháp ngẫu nhiên () Toán học. floor() trả về giá trị số nguyên gần nhất được tạo bởi Math. ngẫu nhiên() Chỉ mục ngẫu nhiên này sau đó được sử dụng để truy cập một phần tử mảng ngẫu nhiên |