// /next.config.js
module . exports = {
async headers ( ) {
return [ {
source : "/(.*)" ,
headers : createSecureHeaders ( {
contentSecurityPolicy : {
directives : {
defaultSrc : "'self'" ,
styleSrc : [ "'self'" , "https://stackpath.bootstrapcdn.com" ] ,
} ,
} ,
forceHTTPSRedirect : [ true , { maxAge : 60 * 60 * 24 * 4 , includeSubDomains : true } ] ,
referrerPolicy : "same-origin" ,
} )
} ] ;
} ,
} ; createSecureHeaders ใน next.config.js (แนะนำ)withSecureHeaders ส่วนประกอบหน้าในหน้าforceHTTPSRedirectframeGuardnoopennosniffxssProtectioncontentSecurityPolicyexpectCTreferrerPolicycreateSecureHeaderswithSecureHeaderscreateHeadersObjectwithSecureHeaders| คุณสมบัติ | สิ่งที่คุณสามารถทำได้ |
|---|---|
| ⚛ ออกแบบมาสำหรับ next.js | ใช้สำหรับ next.config.js หรือส่วนประกอบหน้าใน /pages |
| กฎที่ใช้เริ่มต้น | ช่วยโครงการของคุณแม้ว่าคุณจะไม่มีความรู้ |
| - พิมพ์ปลอดภัย | คุณสามารถใช้กับ typeScript |
ความปลอดภัยต่อไปจะคล้ายกับหมวกกันน็อกซึ่งตั้งค่าส่วนหัวการตอบกลับ HTTP ที่เกี่ยวข้องกับความปลอดภัยสำหรับ Express.js
next.js รองรับที่จะใช้ในกรอบ node.js เช่น express.js ดังนั้นคุณสามารถใช้หมวกกันน็อกกับโครงการ Next.js ของคุณหากคุณสร้างเซิร์ฟเวอร์ที่กำหนดเอง แต่ทีมพัฒนา Next.js ไม่แนะนำเซิร์ฟเวอร์ที่กำหนดเอง นอกจากนี้พวกเขากำลังทำงานเพื่อนำไปใช้เพื่อให้เป็นไปได้ที่จะใช้ next.js โดยไม่มีเซิร์ฟเวอร์ที่กำหนดเอง ในความเป็นจริง Next.js 9 รองรับการกำหนดเส้นทางแบบไดนามิกดังนั้นเราไม่จำเป็นต้องสร้างเซิร์ฟเวอร์ที่กำหนดเองเพื่อใช้งานโดยใช้เช่นเส้นทางถัดไปซึ่งต้องใช้เซิร์ฟเวอร์ที่กำหนดเอง
// /next.config.js
const { createSecureHeaders } = require ( "next-secure-headers" ) ;
module . exports = {
async headers ( ) {
return [ { source : "/(.*)" , headers : createSecureHeaders ( ) } ] ;
} ,
} ; หากคุณต้องการใช้หมวกกันน็อกต้องใช้เซิร์ฟเวอร์ที่กำหนดเองกับวิธีที่แนะนำ เพื่อแก้ปัญหานี้หัวคนต่อไปเกิด ความปลอดภัยต่อไปจะถูกสร้างขึ้นสำหรับโครงการ next.js เพื่อให้คุณสามารถระบุส่วนหัวใด ๆ ในส่วนประกอบ next.config.js หรือหน้า
ต่อไปนี้เป็นกฎข้อที่ปลอดภัยต่อไปและหมวกกันน็อกมี หัวที่ปลอดภัยต่อไปได้รับแรงบันดาลใจจากหมวกกันน็อก แต่มันไม่มีกฎบางอย่างด้วยเหตุผลบางอย่าง
| ความปลอดภัยต่อไป | หมวกนิรภัย | การแสดงความคิดเห็น | |
|---|---|---|---|
| ความปลอดภัยที่เข้มงวด | forceHTTPSRedirect | hsts | |
| ตัวเลือก X-Frame | frameGuard | frameguard | |
| ตัวเลือก X-Download | noopen | ieNoOpen | |
| ตัวเลือก X-Content-type | nosniff | noSniff | |
| การป้องกัน X-XSS | xssProtection | xssFilter | |
| นโยบายความปลอดภัยของเนื้อหา | contentSecurityPolicy | contentSecurityPolicy | |
| คาดหวัง-CT | expectCT | expectCt | |
| นโยบายการอ้างอิง | referrerPolicy | referrerPolicy | |
| X-DNS-Prefetch-Control | - | dnsPrefetchControl | สิ่งนี้มีผลกระทบด้านความเป็นส่วนตัว แต่สิ่งนี้ช่วยปรับปรุงประสิทธิภาพ |
| นโยบายฟีเจอร์ | - | featurePolicy | นโยบายคุณสมบัติปรับปรุงความปลอดภัย แต่ยังทำงานได้ |
| X-powered-by | - | hidePoweredBy | next.js รองรับการลบส่วนหัวนี้ใน next.config.js |
| เกี่ยวข้องกับแคช | - | nocache | ดังที่หมวกกันน็อกกล่าวว่าการแคชมีประโยชน์มากมาย |
| X-permitted-cross-domain-policies | - | crossdomain | Adobe Flash เป็นหนึ่งในเทคโนโลยีเว็บเก่า |
$ npm install -D next-secure-headersหากคุณใช้เส้นด้ายให้ใช้คำสั่งต่อไปนี้
$ yarn add -D next-secure-headers❗ สำหรับ
withSecureHeadersหากคุณต้องการใช้withSecureHeadersคุณต้องติดตั้งโดยไม่มีตัวเลือก-D(เช่นการติดตั้งเป็นการdependenciesไม่ได้devDependencies)
มีสองวิธีในการระบุส่วนหัว หนึ่งคือการใช้ createSecureHeaders ใน next.config.js และอีกอย่างคือการใช้ withSecureHeaders ส่วนประกอบหน้า
createSecureHeaders ใน next.config.js (แนะนำ)❗ next.js 9.5 หรือสูงกว่าเป็นสิ่งจำเป็น ฟังก์ชั่น
headersได้รับการสนับสนุนตั้งแต่ next.js 9.5 ดังนั้นคุณต้องใช้ next.js 9.5 หรือสูงกว่าถ้าคุณต้องการใช้วิธีนี้
- สำหรับเส้นทาง Next.js 10 และ i18n หากโครงการของคุณใช้เส้นทาง Next.js 10 และเส้นทาง I18N ในตัวและคุณต้องการใช้กฎสำหรับทุกหน้าคุณต้องระบุ
"/:path*"เพื่อแหล่งที่sourceแทน"/(.*)"ในทางกลับกันหากโครงการของคุณไม่ได้ใช้เส้นทาง i18n แม้ว่าจะใช้ next.js 10 คุณต้องระบุ"/(.*)"แทน ข้อ จำกัด เหล่านี้อาจเป็นข้อบกพร่องใน next.js
วิธีนี้ใช้ฟังก์ชั่น createSecureHeaders และวิธีการกำหนดค่าส่วนหัวในตัวโดย next.js ไม่จำเป็นต้องใช้เซิร์ฟเวอร์ใด ๆ สามารถใช้ในหน้าคงที่และสามารถรักษาการเพิ่มประสิทธิภาพแบบคงที่อัตโนมัติ หากโครงการของคุณไม่ได้ใช้เซิร์ฟเวอร์ใด ๆ (โดยใช้หน้าคงที่หรือ SSG) หรือคุณเพิ่งสร้างโครงการถัดไป JS ฉันขอแนะนำให้เก็บหน้าคงที่และใช้วิธีนี้
นำเข้า createSecureHeaders จากหัวที่ปลอดภัยถัดไปและใช้ในฟังก์ชัน headers async ใน next.config.js
// /next.config.js
const { createSecureHeaders } = require ( "next-secure-headers" ) ;
module . exports = {
async headers ( ) {
return [ { source : "/(.*)" , headers : createSecureHeaders ( ) } ] ;
} ,
} ;โดยค่าเริ่มต้นหัวความปลอดภัยถัดไปจะใช้กฎบางอย่าง หากคุณต้องการเปิดใช้งานหรือปิดการใช้งานกฎคุณสามารถให้ตัวเลือกกับอาร์กิวเมนต์แรกของฟังก์ชัน
module . exports = {
async headers ( ) {
return [ {
source : "/(.*)" ,
headers : createSecureHeaders ( {
contentSecurityPolicy : {
directives : {
defaultSrc : "'self'" ,
styleSrc : [ "'self'" , "https://stackpath.bootstrapcdn.com" ] ,
} ,
} ,
forceHTTPSRedirect : [ true , { maxAge : 60 * 60 * 24 * 4 , includeSubDomains : true } ] ,
referrerPolicy : "same-origin" ,
} ) ,
} ] ;
} ,
} ;นอกจากนี้คุณสามารถกำหนดค่าส่วนหัวที่แตกต่างกันโดย URL ตามเอกสารอย่างเป็นทางการ
withSecureHeaders ส่วนประกอบหน้าในหน้า❗ จำเป็นต้องใช้เซิร์ฟเวอร์ ด้วยวิธีนี้ต้องใช้เซิร์ฟเวอร์ใด ๆ เพราะ
withSecureHeadersใช้getServerSidePropsของ Next.js.
ใช้ฟังก์ชั่นที่ส่งออกสำหรับแอปพลิเคชัน next.js ของคุณใน /pages/_app.tsx นอกจากนี้คุณสามารถใช้ในส่วนประกอบของหน้าใด ๆ ใน /pages/xxx.tsx แทน
// /pages/_app.tsx
import { withSecureHeaders } from "next-secure-headers" ;
class Application extends App {
...
}
export default withSecureHeaders ( ) ( Application ) ;โดยค่าเริ่มต้นหัวความปลอดภัยถัดไปจะใช้กฎบางอย่าง หากคุณต้องการเปิดใช้งานหรือปิดการใช้งานกฎคุณสามารถให้ตัวเลือกกับอาร์กิวเมนต์แรกของฟังก์ชัน
export default withSecureHeaders ( {
contentSecurityPolicy : {
directives : {
defaultSrc : "'self'" ,
styleSrc : [ "'self'" , "https://stackpath.bootstrapcdn.com" ] ,
} ,
} ,
forceHTTPSRedirect : [ true , { maxAge : 60 * 60 * 24 * 4 , includeSubDomains : true } ] ,
referrerPolicy : "same-origin" ,
} ) ( Application ) ; forceHTTPSRedirect {
forceHTTPSRedirect: boolean | [ true , Partial < { maxAge : number ; includeSubDomains : boolean ; preload : boolean } > ] ;
}| ค่าเริ่มต้น | MDN |
|---|---|
[true, { maxAge: 63072000 }] | https://developer.mozilla.org/docs/web/http/headers/strict-transport-security |
นี่คือการตั้งค่าส่วนหัว "การแปลความปลอดภัยที่เข้มงวด (HSTS)" และเพื่อป้องกันการโจมตีแบบ man-in-the-middle ในระหว่างการเปลี่ยนเส้นทางจาก HTTP ไปยัง HTTPS เพื่อเปิดใช้งานสิ่งนี้ขอแนะนำอย่างยิ่งหากคุณใช้ HTTPS (SSL) บนเซิร์ฟเวอร์ของคุณ
คุณสามารถให้ true หากคุณต้องการเปิดใช้งานกฎนี้หรือคุณสามารถระบุตัวเลือกได้โดยให้ [true, OPTION_OBJECT] โดยค่าเริ่มต้นจะตั้ง max-age เป็นสองปี (63,072,000 วินาที)
frameGuard {
frameGuard: false | "deny" | "sameorigin" | [ "allow-from" , { uri : string | URL } ] ;
}| ค่าเริ่มต้น | MDN |
|---|---|
"deny" | https://developer.mozilla.org/docs/web/http/headers/x-frame-options |
นี่คือการตั้งค่าส่วนหัว "X-frame-options" และเพื่อป้องกันการโจมตีแบบคลิก "deny" แนะนำเป็นอย่างยิ่งหากคุณไม่ได้ใช้องค์ประกอบเฟรมเช่น iframe
noopen {
noopen: false | "noopen" ;
}| ค่าเริ่มต้น | MDN |
|---|---|
"noopen" | https://developer.mozilla.org/docs/web/http/headers/x-download-options |
นี่คือการตั้งค่าส่วนหัว "X-Download-Options" และเพื่อป้องกันไม่ให้เปิดไฟล์ที่ดาวน์โหลดมาโดยอัตโนมัติสำหรับ IE8+ (การโจมตีการจัดการ MIME)
nosniff {
nosniff: false | "nosniff" ;
}| ค่าเริ่มต้น | MDN |
|---|---|
"nosniff" | https://developer.mozilla.org/docs/web/http/headers/x-content-type-options |
นี่คือการตั้งค่าส่วนหัว "X-content-type-options" และเพื่อป้องกันการโจมตีดมกลิ่น MIME
xssProtection {
xssProtection: false | "sanitize" | "block-rendering" | [ "report" , { uri : string | URL } ] ;
}| ค่าเริ่มต้น | MDN |
|---|---|
"sanitize" | https://developer.mozilla.org/docs/web/http/headers/x-xss-protection |
นี่คือการตั้งค่าส่วนหัว "X-XSS-Protection" และเพื่อป้องกันการโจมตี XSS
หากคุณระบุ "sanitize" สิ่งนี้จะกำหนดส่วนหัวเป็น "1" และเบราว์เซอร์จะทำให้พื้นที่ที่ไม่ปลอดภัย หากคุณระบุ "block-rendering" สิ่งนี้จะตั้งส่วนหัวเป็น "1; mode=block" และเบราว์เซอร์จะบล็อกการแสดงผลหน้า "X-XSS-Protection" บล็อกการโจมตี XSS จำนวนมาก แต่แนะนำให้ใช้นโยบายความปลอดภัยของเนื้อหาเมื่อเทียบกับสิ่งนี้
contentSecurityPolicy {
contentSecurityPolicy :
| false
| {
directives :
& Partial < {
childSrc : string | string [ ] ;
connectSrc : string | string [ ] ;
defaultSrc : string | string [ ] ;
fontSrc : string | string [ ] ;
frameSrc : string | string [ ] ;
imgSrc : string | string [ ] ;
manifestSrc : string | string [ ] ;
mediaSrc : string | string [ ] ;
prefetchSrc : string | string [ ] ;
objectSrc : string | string [ ] ;
scriptSrc : string | string [ ] ;
scriptSrcElem : string | string [ ] ;
scriptSrcAttr : string | string [ ] ;
styleSrc : string | string [ ] ;
styleSrcElem : string | string [ ] ;
styleSrcAttr : string | string [ ] ;
workerSrc : string | string [ ] ;
} >
& Partial < {
baseURI : string | string [ ] ;
pluginTypes : string | string [ ] ;
sandbox :
| true
| "allow-downloads-without-user-activation"
| "allow-forms"
| "allow-modals"
| "allow-orientation-lock"
| "allow-pointer-lock"
| "allow-popups"
| "allow-popups-to-escape-sandbox"
| "allow-presentation"
| "allow-same-origin"
| "allow-scripts"
| "allow-storage-access-by-user-activation"
| "allow-top-navigation"
| "allow-top-navigation-by-user-activation" ;
} >
& Partial < {
formAction : string | string [ ] ;
frameAncestors : string | string [ ] ;
navigateTo : string | string [ ] ;
reportURI : string | URL | ( string | URL ) [ ] ;
reportTo : string ;
} > ;
reportOnly?: boolean ;
} ;
}| ค่าเริ่มต้น | MDN |
|---|---|
false | https://developer.mozilla.org/docs/web/http/headers/content-security-policy |
นี่คือการตั้งค่าส่วนหัว "นโยบายความปลอดภัยเนื้อหา" หรือ "ส่วนหัวที่ให้ความสำคัญกับการรายงานความปลอดภัยของเนื้อหาเท่านั้นและเพื่อป้องกันการโหลดและดำเนินการทรัพยากรที่ไม่ได้รับอนุญาต
หากคุณให้ความจริงกับ reportOnly อย่างแท้จริงสิ่งนี้จะตั้งค่า "เนื้อหาที่ให้ความปลอดภัย-นโยบาย-รายงานอย่างเดียว" เพื่อให้คุณค่าแทนที่จะเป็น "นโยบายความปลอดภัยของเนื้อหา"
นอกจากนี้คุณสามารถระบุคำสั่งโดยใช้ชื่อโซ่เคสเช่น child-src แทน childSrc
❗เมื่อตั้งค่า
frameAncestors: X-Frame-options จะให้ความสำคัญ ส่วน "ความสัมพันธ์กับ X-Frame-options" ของข้อมูลจำเพาะ CSP กล่าวว่า: "หากมีการส่งทรัพยากรด้วยนโยบายที่มีคำสั่งชื่อ-ทนายเฟรมและการจัดการคือ" บังคับใช้ "แล้วส่วนหัวของ X-Frame-Options จะต้องถูกเพิกเฉย"ดังนั้นหากการตั้งค่า
frameAncestorsคุณควรตั้งค่าframeGuardเป็นfalse
expectCT {
expectCT: boolean | [ true , Partial < { maxAge : number ; enforce : boolean ; reportURI : string | URL } > ] ;
}| ค่าเริ่มต้น | MDN |
|---|---|
false | https://developer.mozilla.org/docs/web/http/headers/expect-ct |
นี่คือการตั้งค่าส่วนหัว "คาดว่าจะเป็น CT" และบอกให้เบราว์เซอร์คาดหวังความโปร่งใสของใบรับรอง
referrerPolicy {
referrerPolicy :
| false
| "no-referrer" | "no-referrer-when-downgrade" | "origin" | "origin-when-cross-origin" | "same-origin" | "strict-origin" | "strict-origin-when-cross-origin"
| ( "no-referrer" | "no-referrer-when-downgrade" | "origin" | "origin-when-cross-origin" | "same-origin" | "strict-origin" | "strict-origin-when-cross-origin" ) [ ] ;
}| ค่าเริ่มต้น | MDN |
|---|---|
false | https://developer.mozilla.org/docs/web/http/headers/referrer-policy |
นี่คือการตั้งค่าส่วนหัว "ผู้อ้างอิงนโยบาย" และเพื่อป้องกันไม่ให้มีการอ้างอิงจากเซิร์ฟเวอร์อื่น ๆ คุณสามารถระบุค่าหนึ่งหรือมากกว่าสำหรับเบราว์เซอร์ดั้งเดิมซึ่งไม่รองรับค่าที่เฉพาะเจาะจง
createSecureHeaders import { createSecureHeaders } from "next-secure-headers" ;
createSecureHeaders ( { referrerPolicy : "same-origin" } ) ;
// [
// {
// key: "Referrer-Policy",
// value: "same-origin",
// },
// ] createSecureHeaders เป็นฟังก์ชันที่จะส่งคืนส่วนหัวเป็นวัตถุต่อไปนี้รูปแบบเช่น { key, value }
createSecureHeaders ( OPTIONS ) ;อาร์กิวเมนต์แรกยอมรับตัวเลือกสำหรับกฎ
withSecureHeaders import { withSecureHeaders } from "next-secure-headers" ;
export default withSecureHeaders ( { referrerPolicy : "same-origin" } ) ( Page ) ; withSecureHeaders เป็นส่วนหนึ่งในการระบุส่วนหัวโดยใช้ getServerSideProps คุณสามารถใช้ฟังก์ชั่นนี้สำหรับแอปพลิเคชัน ( /pages/_app.tsx ) และส่วนประกอบหน้า ( /pages/xxx.tsx ) สิ่งนี้ไม่สามารถใช้ได้ใน next.config.js
withSecureHeaders ( OPTIONS ) ( APPLICATION_OR_COMPONENT ) ;อาร์กิวเมนต์แรกยอมรับตัวเลือกสำหรับกฎและอาร์กิวเมนต์ของฟังก์ชั่นที่ส่งคืนยอมรับแอปพลิเคชันหรือส่วนประกอบหน้า ค่าที่ส่งคืนเป็นองค์ประกอบปฏิกิริยาใหม่
createHeadersObject import { createHeadersObject } from "next-secure-headers" ;
createHeadersObject ( { referrerPolicy : "same-origin" } ) ;
// {
// "Referrer-Policy": "same-origin",
// } createHeadersObject เป็นฟังก์ชันที่จะส่งคืนส่วนหัวเป็นวัตถุ
createHeadersObject ( OPTIONS ) ;อาร์กิวเมนต์แรกยอมรับตัวเลือกสำหรับกฎ
โดยทั่วไปแล้วส่วนหัวการตอบกลับ HTTP ที่ขับเคลื่อนด้วย X ควรถูกลบออกจากส่วนหัวการตอบกลับเนื่องจากช่วยให้แฮกเกอร์ได้รับข้อมูลเซิร์ฟเวอร์
หัวที่ปลอดภัยถัดไปไม่สนับสนุนเพื่อลบส่วนหัวที่ใช้ X-powered-by แต่ next.js รองรับการทำ
// next.config.js
module . exports = {
poweredByHeader : false ,
} ; หากคุณให้เท็จกับ poweredByHeader ใน next.config.js , next.js จะลบส่วนหัวออกจากส่วนหัวการตอบกลับ
withSecureHeaders // /pages/_app.tsx
export default withSecureHeaders ( { referrerPolicy : "same-origin" } ) ( Application ) ;
// /pages/about.tsx
export default withSecureHeaders ( { referrerPolicy : "no-referrer-when-downgrade" } ) ( Page ) ;
// But actually the server responds "same-origin"...หัวที่ปลอดภัยต่อไปไม่สนับสนุนการแทนที่ส่วนหัวการตอบสนองในส่วนประกอบหน้าเด็กเนื่องจากถูก จำกัด โดยสถาปัตยกรรม next.js
// /config/secure-headers.ts
import { withSecureHeaders } from "next-secure-headers" ;
export const secureHeadersDefaultOption : Parameters < typeof withSecureHeaders > [ 0 ] = {
referrerPolicy : "same-origin" ,
} ;
// /pages/_app.tsx
import { secureHeadersDefaultOption } from "../config/secure-headers" ;
export default withSecureHeaders ( secureHeadersDefaultOption ) ( Application ) ;
// /pages/about.tsx
export default withSecureHeaders ( {
... secureHeadersDefaultOption ,
referrerPolicy : "no-referrer-when-downgrade" ,
} ) ( Page ) ;ในการแก้ปัญหานี้คุณควรกำหนดตัวเลือกเป็นโมดูลเดียวจากนั้นคุณควรนำเข้าและรวมวัตถุ
รายงานข้อผิดพลาดและคำขอดึงยินดีต้อนรับบน GitHub ที่ https://github.com/jagaapple/next-secure-headers โครงการนี้มีจุดประสงค์เพื่อเป็นพื้นที่ที่ปลอดภัยและเป็นมิตรสำหรับการทำงานร่วมกันและผู้สนับสนุนคาดว่าจะปฏิบัติตามจรรยาบรรณของผู้สนับสนุน
โปรดอ่านแนวทางที่มีส่วนร่วมก่อนการพัฒนาและมีส่วนร่วม
ห้องสมุดมีให้เป็นโอเพ่นซอร์สภายใต้ข้อกำหนดของใบอนุญาต MIT
ลิขสิทธิ์ 2020 Jaga Apple สงวนลิขสิทธิ์