เราสามารถใช้window.location.replace
เพื่อหลีกเลี่ยงประวัติและกำหนดเป้าหมายจุดยึดบนหน้าโดยไม่ต้องโหลดหน้าใหม่แต่ไม่ใช่ iframes?
ปัญหาคือการละเมิด CSP (นโยบายความปลอดภัยของเนื้อหา)ซึ่งscript-src 'unsafe-inline'
ต้องเปิดใช้งานสถานะ ยกเว้นว่าฉันไม่ได้กำหนด CSP และแม้ว่าฉันจะกำหนดไว้และให้script-src 'unsafe-inline'
มันยังคงให้ข้อผิดพลาดการละเมิดเดียวกัน ผลลัพธ์เดียวกันคือ 11 / chrome / ff
Iframe บนโดเมนเดียวกัน(ในไดเรกทอรีเดียวกัน)
- กำหนดเป้าหมาย iframe ในคอนโซลและใช้
window.location.replace('/samepage.html#onpage_anchor')
ในคอนโซล - มันได้ผล. มันกำหนดเป้าหมายที่สมอหน้าโดยไม่ต้องโหลดหน้าซ้ำและไม่มีประวัติ
- ใส่รหัสเดียวกันแบบอินไลน์ในลิงก์จุดยึดและใช้งานได้
- ใช้รหัสเดียวกันในสคริปต์ภายนอกรับข้อผิดพลาดการละเมิด csp วิธีนี้ใช้ได้ผลดีหากไม่ได้อยู่ใน iframe
ฉันพยายามสร้าง CSPจะอนุญาตให้มีการดำเนินการ แต่ไม่ได้ที่สุดอนุญาตนโยบายการรักษาความปลอดภัยข้อมูลที่เป็นไปได้จะช่วยให้มัน
แก้ไข: ดังนั้นฉันจึงรวบรวมตัวอย่างบน plunker ซึ่งอนุญาตให้มีหลายไฟล์ดังนั้นฉันจึงสามารถใช้href ที่เหมาะสมซึ่งอ้างอิงหน้าแม่ / ลูก
หมายเหตุเกี่ยวกับตัวอย่างของผู้รวบรวม:
ปัญหาไม่ได้ทำซ้ำในตัวอย่างเหล่านี้ สคริปต์ทำงานได้อย่างสมบูรณ์แบบแม้ใน iframe อย่างไรก็ตามรหัสเดียวกันไม่สามารถใช้งานได้บนเซิร์ฟเวอร์ภายในเครื่องของฉันหรือเมื่อฉันเรียกใช้งานมันบน VPS
ฉันสงสัยว่าการละเมิด CSP ไม่ได้รับการทริกเกอร์จากผู้รวบรวมเพราะผู้รวบรวมกำลังแสดงเนื้อหาไปยังเบราว์เซอร์ผ่านเลเยอร์สิ่งที่เป็นนามธรรมบางประเภท
ครั้งแรกที่คุณคลิกลิงก์หีบเพลงในพาเรนต์มันจะทำให้รีเฟรช นี่เป็นเพราะวิธีการโหลดหน้าเว็บในตอนแรกมันไม่ได้อ้างอิง index.html การคลิกครั้งต่อไปจะทำงานตามที่คาดไว้โดยไม่ต้องโหลดหน้าซ้ำ ไม่ใช่ปัญหาใน iframe เนื่องจากจะอ้างอิง child.html ในขั้นต้น
นี่เป็นตัวอย่างที่ดีในการแสดงรหัสโดยไม่ต้องมีการแก้ไขเพื่อให้มันทำงานได้(เช่นในความต้องการที่จะเปลี่ยน hrefs เพื่อให้มันทำงานในตัวอย่างสแต็กโอเวอร์โฟลว์ตามที่ระบุไว้ด้านล่าง) มันดีเหมือนกันเพราะมันแสดงให้เห็นว่าจาวาสคริปต์ทำงานได้ดีเท่าที่ควร แต่มันไม่แสดงปัญหาจริง คุณยังจะต้องโหลดมันขึ้นมาในโปรแกรมแก้ไขของคุณและเรียกใช้มันบนเซิร์ฟเวอร์ท้องถิ่นหรือสภาพแวดล้อมการโฮสต์สดเพื่อดูปัญหาจริง
ตัวอย่างงานพลั่ว
ด้วยสคริปต์: ไม่มีประวัติ
ไม่มีสคริปต์: ด้วยประวัติ
ตัวอย่างรหัสแบบย่อ
หีบเพลงที่เรียบง่ายด้วยหนึ่งรายการ เพียงพอที่จะทำให้เกิดปัญหา
การคลิกที่เปิด / ปิดจะเป็นการขยาย / ยุบหีบเพลงโดยไม่จำเป็นต้องใช้ JS JS ควรทำสิ่งเดียวกัน แต่ไม่มีประวัติ ทำงานได้ดี แต่ไม่ใช่ใน iframe
หมายเหตุข้อมูลโค้ด:
คุณสามารถเรียกใช้ข้อมูลโค้ดเพื่อรับความคิดเกี่ยวกับสิ่งที่ฉันกำลังอธิบายแต่จริง ๆ แล้วไม่ได้แสดงให้เห็นถึงปัญหา
ตัวอย่างข้อมูลไม่ทำงานเหมือนในเบราว์เซอร์จริง ๆ จาวาสคริปต์ไม่ทำงาน
ตัวอย่างแสดงรหัส แต่ควรเรียกใช้ใน iframe เพื่อดูปัญหา เรียกใช้นอก iframe เพื่อดูความแตกต่างและวิธีการทำงาน
- เนื่องจากลิงก์ทำงานร่วมกับ JS (แทนที่ URL ทั้งหมด) ลิงก์เหล่านั้นจึงต้องเป็นแบบนี้
href="https://stackoverflow.com/thispage.html#ac1"
มากกว่าhref="#ac1"
ที่จะปรากฏในข้อมูลโค้ด (ไม่สามารถกำหนดเป้าหมายหน้า html จริงในตัวอย่างได้) ดังนั้นหากคุณลองใช้ตัวแก้ไขของคุณ (โปรดทำ)อย่าลืมเปลี่ยนลิงค์ไปยังรูปแบบนี้this_document.html#anchor
เพื่อให้พวกเขายังคงเป็นจุดยึดของหน้าเดียวกันแต่page.html รวมอยู่ในลิงค์
สคริปต์
$(document).ready(function() {
// anchor links without history
$.acAnch = function(event) {
event.preventDefault();
var anchLnk = $(event.target);
var anchTrgt = anchLnk.attr('href');
window.location.replace(anchTrgt);
}
// listen for anchor clicks
$('.accordion').on('click', 'a', $.acAnch);
});
นี้เป็นเรื่องง่ายมาก:
1. ฟังก์ชั่น acAnch เตะแอตทริบิวต์และหยดลงในhref
2. ฟังการคลิกที่จุดยึดภายในหีบเพลงเพื่อเรียกใช้ฟังก์ชั่น acAnchwindow.location.replace()
ดังนั้นสคริปต์ทั้งหมดจะถูกเรียกใช้ window.location.replace('/this_same_page.html#on_page_anchor')
หากคุณวางสิ่งนั้นไว้ในคอนโซลมันก็ใช้งานได้ไม่มีการละเมิด CSP แต่การเรียกใช้จากสคริปต์ภายนอกไม่ทำงาน
อินไลน์บนลิงก์ใช้งานได้ดี:
onclick="event.preventDefault();window.location.replace('/thispage.html#acc0');"
onclick="event.preventDefault();window.location.replace('/thispage.html#acc1');"
การใส่ลิงก์นั้นให้ทำงานได้อย่างสมบูรณ์แบบแต่ฉันไม่ต้องการใช้สคริปต์แบบอินไลน์เช่นนั้น ต้องมีวิธีในการทำเช่นนี้กับสคริปต์ภายนอก
ฉันพยายามเรียกใช้ javascript บนพาเรนต์แทนที่จะเป็นใน iframe (พร้อมการแก้ไขเพื่อเลือกลิงค์ภายในลูกของหลักสูตร) ผลลัพธ์ข้อผิดพลาด CSP เดียวกัน
ทำไมฉันถึงทำเช่นนี้?
เว็บไซต์มีความซับซ้อนมากกว่าตัวอย่าง จุดยึดใน iframes ทำงานได้ดี แต่เพิ่มประวัติ หากคุณรันโค้ดด้านบนโดยไม่ใช้ javascript (หรือเรียกใช้ส่วนย่อย) ให้เปิดและปิดหีบเพลงสองสามครั้งและใช้ปุ่มย้อนกลับมันจะย้อนกลับไปยังสถานะปิดที่เปิดอยู่
ฉันจะไม่รังเกียจประวัติแต่ถ้าอยู่ใน iframe เมื่อคุณออกจากหน้าหลักแล้วกลับมาประวัติความเป็นมาใน iframe จะแตก การย้อนกลับไม่ได้ย้อนกลับไปยังรัฐหีบเพลงอีกต่อไป แต่แทนที่จะโหลด iframe ต่อไป เริ่มแรกจุดยึดไม่ทำให้เกิดการโหลด iframe แต่เพียงทำตามขั้นตอนผ่านประวัติสถานะหีบเพลงที่ใช้งานได้ดีจนกว่าคุณจะออกจากหน้าและกลับมา จากนั้นกลับไม่ผ่านไปยังรัฐหีบเพลงอีกต่อไปแต่เพิ่งผ่านกองโหลด iframe ที่เหมือนกันอีกครั้ง มันเป็นพฤติกรรมที่ไม่เป็นมิตรของผู้ใช้
ฉันไม่จำเป็นต้องใช้ location.replace หากมีวิธีอื่นที่ใช้งานได้ ฉันได้ลองวิธีอื่น ๆ แล้วและฉันพบว่าวิธีการที่สามารถบรรลุผลลัพธ์เดียวกันโดยทั่วไปแล้วจะทำให้เกิดข้อผิดพลาดเดียวกัน
เป้าหมายคือเพื่อเปิดใช้งานการเชื่อมโยงจุดยึดบนหน้าโดยไม่ต้องโหลดซ้ำและไม่มีประวัติ ภายใน iframe
สคริปต์แบบอินไลน์ทำงาน เราสามารถทำให้มันทำงานในไฟล์. js ภายนอกได้หรือไม่?
<a href="#ac0" class="ac-close">Close</a>
ควรทำงาน