Tôi có thể sử dụng window.location.replace trong iframe không?


15

Chúng ta có thể sử dụng window.location.replaceđể tránh lịch sửnhắm mục tiêu các neo trên trang mà không cần tải lại trang, nhưng không phải trong iframe?

Vấn đề là vi phạm CSP (chính sách bảo mật nội dung), trạng thái script-src 'unsafe-inline'phải được bật. Ngoại trừ tôi không có CSP được xác định và ngay cả khi tôi xác định một CSP và cho phép script-src 'unsafe-inline'nó vẫn đưa ra lỗi vi phạm tương tự. Kết quả tương tự trong eg11 / chrome / ff.

Iframe trên cùng một tên miền (trong cùng thư mục).

  1. Nhắm mục tiêu iframe trong bàn điều khiển và sử dụng window.location.replace('/samepage.html#onpage_anchor')trong bàn điều khiển.
  2. nó hoạt động Nó nhắm mục tiêu neo trên trang mà không cần tải lại trang và không có lịch sử.
  3. Đặt cùng mã nội tuyến trên các liên kết neo và nó hoạt động.
  4. Sử dụng cùng một mã trong tập lệnh bên ngoài, nhận được lỗi vi phạm csp. Điều này hoạt động tốt nếu không trong iframe.

Tôi đã cố gắng tạo ra một CSP để cho phép các hành động, nhưng thậm chí không những dễ dãi nhất chính sách bảo mật nội dung có thể sẽ cho phép nó.


Chỉnh sửa: vì vậy tôi tập hợp các ví dụ trên plunker cho phép nhiều tệp để tôi có thể sử dụng href href tham chiếu các trang cha / con.

Ghi chú về các ví dụ về plunker:

  1. Vấn đề không được sao chép trong các ví dụ này. Kịch bản hoạt động hoàn hảo, ngay cả trong iframe. Tuy nhiên, cùng một mã không hoạt động trên máy chủ cục bộ của tôi hoặc khi tôi chạy nó trực tiếp trên VPS.

  2. Tôi nghi ngờ vi phạm CSP không được kích hoạt trên plunker vì plunker đang trình bày nội dung cho trình duyệt thông qua một loại lớp trừu tượng nào đó.

  3. Lần đầu tiên bạn nhấp vào các liên kết accordion trong cha mẹ, nó gây ra một sự làm mới. Điều này là do cách trang ban đầu tải nó không tham chiếu index.html. Các lần nhấp tiếp theo hoạt động như mong đợi mà không cần tải lại trang. Không phải là vấn đề trong iframe vì ban đầu nó tham chiếu child.html

  4. Đây là những ví dụ tốt để hiển thị mã mà không yêu cầu thay đổi để làm cho nó hoạt động (vì cần phải thay đổi href để làm cho chúng hoạt động trong đoạn trích stackoverflow, được đề cập bên dưới). Nó cũng tốt vì nó cho thấy javascript hoạt động như bình thường. Nhưng nó không hiển thị vấn đề thực sự. Bạn vẫn sẽ cần tải nó lên trong trình soạn thảo của mình và chạy nó trên máy chủ cục bộ hoặc môi trường lưu trữ trực tiếp để xem vấn đề thực sự.

Ví dụ về Plunker

Với kịch bản: Không có lịch sử
Không có kịch bản: Với lịch sử


Ví dụ mã đơn giản

Accordion đơn giản với một mục. Đủ để tái tạo vấn đề.

Nhấp vào mở / đóng sẽ mở rộng / thu gọn accordion, không yêu cầu JS. JS nên làm điều tương tự chính xác nhưng không có lịch sử. Hoạt động tốt, nhưng không trong iframe.

Đoạn mã ghi chú:

  1. Bạn có thể chạy đoạn trích để có ý tưởng về những gì tôi đang mô tả, nhưng nó không thực sự chứng minh vấn đề.

  2. Đoạn mã không hoạt động như trong trình duyệt thực, javascript không hoạt động.

  3. Đoạn mã hiển thị mã, nhưng nó phải được chạy trong iframe để xem vấn đề. Chạy nó bên ngoài iframe để thấy sự khác biệt và cách nó hoạt động.

  1. Do cách các liên kết hoạt động với JS (thay thế toàn bộ url), chúng thực sự phải giống như thế này href="https://stackoverflow.com/thispage.html#ac1"thay vì chỉ href="#ac1"xuất hiện trong đoạn trích (không thể nhắm mục tiêu trang html thực tế trong đoạn trích). Vì vậy, nếu bạn thử điều này trong trình chỉnh sửa của mình (vui lòng làm), thì hãy nhớ thay đổi các liên kết thành định dạng này this_document.html#anchor để chúng vẫn là các neo trang giống nhau, nhưng page.html được bao gồm trong liên kết.


Kịch bản

$(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);

    });

Điều này rất đơn giản:
1. Hàm acAnch lấy hrefthuộc tính và thả nó vào window.location.replace().
2. Lắng nghe các nhấp chuột trên các neo trong accordion để chạy chức năng acAnch.

Vì vậy, tất cả các kịch bản làm là chạy window.location.replace('/this_same_page.html#on_page_anchor')

Nếu bạn đặt nó trong bàn điều khiển thì nó hoạt động, không vi phạm CSP. Nhưng chạy nó từ kịch bản bên ngoài không hoạt động.

Nội tuyến trên các liên kết hoạt động tốt:

onclick="event.preventDefault();window.location.replace('/thispage.html#acc0');"
onclick="event.preventDefault();window.location.replace('/thispage.html#acc1');"

Đặt nó trên các liên kết tương ứng hoạt động hoàn hảo , nhưng tôi thực sự không thích sử dụng tập lệnh nội tuyến như thế. Phải có một cách để làm điều này với một kịch bản bên ngoài.

Tôi đã thử chạy javascript trên cha mẹ thay vì trong iframe (với các sửa đổi để chọn các liên kết trong khóa con). Kết quả lỗi CSP tương tự.


Tại sao tôi làm điều này?

Vâng, trang web phức tạp hơn nhiều so với ví dụ. Các neo trong iframe hoạt động tốt nhưng chúng thêm lịch sử. Nếu bạn chạy mã ở trên mà không có javascript, (hoặc chỉ chạy đoạn mã), hãy mở và đóng accordion một vài lần và sử dụng nút quay lại, nó sẽ quay trở lại qua trạng thái đóng mở.

Tôi sẽ không quan tâm đến lịch sử, nhưng nếu nó nằm trong iframe, khi bạn rời khỏi trang mẹ và sau đó quay lại nó, lịch sử trong iframe bị phá vỡ. Quay trở lại không quay trở lại qua các trạng thái accordion nữa, mà thay vào đó chỉ tiếp tục tải lại iframe. Ban đầu, các neo không gây ra tải lại iframe mà chỉ bước qua lịch sử trạng thái accordion, hoạt động tốt, cho đến khi bạn rời khỏi trang và quay lại. Sau đó trở lại không còn đi qua các trạng thái accordion, mà chỉ đi qua một đống iframe giống nhau tải lại. Đó là hành vi rất thân thiện với người dùng.

Tôi không cần sử dụng location.replace nếu có một phương pháp khác sẽ hoạt động. Mặc dù vậy, tôi đã thử nhiều cách tiếp cận khác và tôi thấy rằng các phương pháp có thể đạt được kết quả tương tự, thường dẫn đến cùng một lỗi.

Mục tiêu chỉ đơn giản là kích hoạt các liên kết neo trên trang mà không cần tải lại và không có lịch sử bên trong iframe.

Kịch bản nội tuyến hoạt động. Chúng ta có thể làm cho nó hoạt động trong một tệp .js bên ngoài không?


bạn đang cố gắng để đạt được neo? Nếu vậy, <a href="#ac0" class="ac-close">Close</a>nên làm việc.
Mất trí nhớ

Được rồi, tôi thiết lập các ví dụ trên plunker. Thật không may, vấn đề không được sao chép trên plunker. Thay vào đó, kịch bản hoạt động tốt, ngay cả trong iframe. với kịch bản - không có lịch sửkhông có kịch bản có lịch sử . Vấn đề nhỏ trên plunker; liên kết accordion trên cha mẹ gây ra một lần làm mới trang, chỉ lần đầu tiên được nhấp (lần đầu tiên tải không có tham chiếu index.html, vì vậy sau lần nhấp đầu tiên, nó hoạt động như mong đợi, không cần tải lại trang). Không phải là vấn đề đối với iframe vì nó được tải với child.html src.
Veneseme Tyras

Vì vậy, ít nhất với các ví dụ plunker, bạn có thể xem mã hoàn chỉnh và xem nó nên hoạt động như thế nào. Nó không hoạt động trên máy chủ cục bộ của tôi hoặc khi tôi chạy nó trực tiếp trên VPS. Tôi sẽ cập nhật câu hỏi với các liên kết và thông tin plunker.
Veneseme Tyras

1
Tôi đã lấy mã mẫu của bạn đến máy chủ của tôi, nó hoạt động tốt, sau đó tôi đã tạo một ví dụ plunker mới từ ví dụ của bạn plnkr.co/edit/V3kx7LQbTppaQ6V06uZp?p=preview nó cũng hoạt động tốt. Không có kết quả lỗi CSP.
Nhà tư tưởng

Vâng, nó hoạt động tốt trên plunker tôi cũng đã làm. Tôi tò mò về cách thức hoạt động trên máy chủ của bạn, bởi vì sau khi nhận xét của bạn, tôi đã kiểm tra ba lần và tôi không thể làm cho nó hoạt động trên máy chủ trực tiếp hoặc trên máy chủ cục bộ của mình.
Veneseme Tyras

Câu trả lời:



0

bạn có thể sử dụng CSS thay vì thẻ iframe html vì thẻ iframe bị xóa trong html


Hãy xem lại cách trả lời . Làm thế nào chính xác họ sẽ giải quyết vấn đề này bằng cách sử dụng CSS?
camille
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.