Bây giờ chúng ta biết cách lấy đầu vào của người dùng bằng cách sử dụng các biểu mẫu HTML và các yêu cầu POST kích hoạt hàm doPost[]
của các lớp servlet của chúng ta
Nhưng chúng tôi phải rất cẩn thận khi hiển thị đầu vào của người dùng đó, đặc biệt là với những người dùng khác. Chúng tôi không thể chỉ cho phép nội dung tùy ý, vì khi đó những người dùng ác ý có thể thực hiện những hành vi xấu như đưa HTML hoặc JavaScript vào trang của chúng tôi, điều này sẽ cho phép họ chuyển hướng trình duyệt, lấy cắp thông tin hoặc khai thác tập lệnh chéo trang trên trang web của bạn
Thay vào đó, chúng tôi phải làm sạch dữ liệu mà chúng tôi nhận được từ người dùng của mình để dữ liệu đó chỉ chứa nội dung an toàn. Không có một cách tốt nhất để làm điều này mặc dù. Nó giống như một loạt câu hỏi mà bạn phải trả lời và câu trả lời phụ thuộc vào chính xác cách bạn muốn trang web của mình hoạt động và loại nội dung nào bạn muốn cho phép
Ứng dụng web mẫu
Hãy bắt đầu với một ứng dụng web mẫu lấy đầu vào từ người dùng và sau đó hiển thị nó. Đây là lớp servlet của chúng ta
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = request.getParameter["content"];
//redirect to a GET request
response.sendRedirect[request.getRequestURI[]];
}
}
Trong chức năng doGet[]
của nó, servlet này thêm nội dung vào yêu cầu và chuyển tiếp nó tới tệp JSP để hiển thị. Hàm doPost[]
nhận tham số nội dung đã gửi, lưu trữ và sau đó chuyển hướng trở lại yêu cầu GET
Tệp JSP trông như thế này
User Input Example
Content:
${content}
Tệp này chỉ hiển thị nội dung và sau đó là biểu mẫu cho phép người dùng thay đổi nội dung
Cuối cùng, đây là tệp
User Input Example
Content:
${content}
1
MyServlet
MyServlet
MyServlet
/home
Tệp
User Input Example
Content:
${content}
1 ánh xạ URL
User Input Example
Content:
${content}
3 tới servlet của chúng tôi. Chạy servlet này và truy cập http. //máy chủ cục bộ. 8080/home, và bạn sẽ thấy cái nàyBạn có thể nhập một số văn bản để đảm bảo nó hoạt động
Ở đây tôi đã gõ
User Input Example
Content:
${content}
4 và nhấp vào nút
User Input Example
Content:
${content}
5. servlet đã lưu trữ nội dung đó và bây giờ trang JSP hiển thị nội dung đó. Bạn có thể coi đây là một phiên bản rất đơn giản của trang web cho phép bạn gửi bài đăng, như Twitter hoặc Facebook hoặc bất kỳ thứ gìĐầu vào của người dùng không hợp lệ
Nhưng điều gì xảy ra nếu bạn nhập html?
Hãy thử nhập một cái gì đó như
User Input Example
Content:
${content}
6 vào phần nhập văn bản và nhấp vào nút
User Input Example
Content:
${content}
5. Bạn sẽ thấy rằng html được hiển thị trong trangĐiều này là do JSP của chúng tôi chỉ xuất nội dung trực tiếp sang HTML trên dòng này
Vì vậy, nếu
User Input Example
Content:
${content}
8 là
User Input Example
Content:
${content}
6, thì HTML được hiển thị trên màn hình là
MyServlet
MyServlet
MyServlet
/home
0Cho phép người dùng nhập HTML tùy ý có thể gây ra sự cố trên trang web của bạn. Hãy tưởng tượng một trang web như Twitter hoặc Facebook hoặc Tumblr, nơi các bài đăng của một người dùng được hiển thị cho những người dùng khác. Nếu tôi là một người dùng độc hại, tôi có thể
- Làm rối tung định dạng trang web của bạn
- Chuyển hướng trình duyệt của người dùng của bạn đến trang web của riêng tôi
- Ăn cắp dữ liệu người dùng của bạn
- Khai thác tập lệnh chéo trang
Một ví dụ khác, hãy thử nhập nội dung này
Nội dung này chỉ là một
MyServlet
MyServlet
MyServlet
/home
1trở thành
MyServlet
MyServlet
MyServlet
/home
2. Hãy nhớ rằng
MyServlet
MyServlet
MyServlet
/home
3 và
MyServlet
MyServlet
MyServlet
/home
4 được hiển thị dưới dạng
MyServlet
MyServlet
MyServlet
/home
3 và
MyServlet
MyServlet
MyServlet
/home
4 thay vì được phân tích cú pháp dưới dạng thẻ HTMLLàm sạch nội dung để chỉ cho phép HTML an toàn thông qua
MyServlet
MyServlet
MyServlet
/home
7trở thành
MyServlet
MyServlet
MyServlet
/home
8Tách nội dung để không cho phép bất kỳ HTML nào
MyServlet
MyServlet
MyServlet
/home
7trở thành
User Input Example
Content:
${content}
4Thay thế nội dung để người dùng có thể nhập các thẻ không phải HTML mà bạn chuyển đổi sang HTML.
1 trở thành
2, Ví dụ. Lưu ý rằng bạn vẫn phải quyết định phải làm gì với HTML bình thường trộn lẫn với loại nội dung nàyCách tiếp cận bạn chọn tùy thuộc vào cách bạn muốn ứng dụng web của mình hoạt động, mối quan tâm về bảo mật của bạn và thành thật mà nói, bạn muốn đầu tư bao nhiêu thời gian vào phần này trên trang web của mình. [Bạn có làm một việc dễ dàng chỉ mất 5 phút hay bạn dành nhiều thời gian để hoàn thiện quy trình nhập liệu của mình?] Trên thực tế, bạn có thể sẽ sử dụng kết hợp một số tùy chọn ở trên
Nội dung không cho phép
Không cho phép nội dung có lẽ là lựa chọn dễ dàng nhất, nhưng ngay cả khi đó, bạn vẫn có nhiều câu hỏi hơn cần trả lời
- Bạn có muốn sử dụng danh sách trắng để đảm bảo đầu vào chỉ chứa nội dung được phép không?
- Hay bạn muốn sử dụng danh sách đen để kiểm tra nội dung không được phép?
Sử dụng danh sách trắng an toàn hơn nhưng hạn chế hơn. Thông thường, bạn sẽ sử dụng biểu thức chính quy để không cho phép nội dung, cho dù bạn sử dụng danh sách trắng hay danh sách đen
Hãy sửa đổi lớp servlet của chúng ta để sử dụng danh sách trắng chỉ cho phép người dùng nhập chữ cái, số và dấu cách
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
if[!request.getParameter["content"].matches["[\\w*\\s*]*"]]{
request.setAttribute["error", "Please enter only letters, numbers, and spaces."];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
return;
}
this.content = request.getParameter["content"];
response.sendRedirect[request.getRequestURI[]];
}
}
Giờ đây, hàm doPost[]
sử dụng biểu thức chính quy cùng với hàm
4 để đảm bảo giá trị đầu vào chỉ chứa các chữ cái, số và dấu cách. Nếu nó không khớp với biểu thức chính quy của chúng ta, điều đó có nghĩa là đầu vào chứa các ký tự không hợp lệ và servlet sẽ thêm một thuộc tính lỗi và chuyển tiếp yêu cầu tới JSP. Nếu đầu vào khớp với biểu thức chính quy, điều đó có nghĩa là nó chỉ chứa các chữ cái, số và dấu cách và chúng tôi cho phép yêu cầu thông quaBây giờ JSP chỉ hiển thị lỗi nếu nó xuất hiện
User Input Example
${error}
Content:
${content}
Bây giờ hãy thử nhập những thứ như
5
6
7 để thấy rằng đầu vào này tạo ra lỗi. Biểu thức chính quy trong ví dụ này được đơn giản hóa quá mức, do đó, nó cũng không cho phép dấu chấm câu và các chữ cái không phải mã ascii. Đó có thể là điều bạn muốn hoặc không, vì vậy hãy xem lớp
8 để biết thêm thông tin về biểu thức chính quyCách tiếp cận không cho phép một số nội dung này khá phổ biến đối với tên người dùng, đặc biệt là vì bạn có thể sẽ sử dụng chúng trong các URL có yêu cầu nội dung riêng. Vì vậy, bạn có thể không muốn tên người dùng là
9 hoặc nhiều khoảng trống hoặc nội dung HTMLthoát khỏi nội dung
Các thẻ HTML được phân định bằng các ký hiệu
MyServlet
MyServlet
MyServlet
/home
3 và
MyServlet
MyServlet
MyServlet
/home
4, như trongimport java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
if[!request.getParameter["content"].matches["[\\w*\\s*]*"]]{
request.setAttribute["error", "Please enter only letters, numbers, and spaces."];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
return;
}
this.content = request.getParameter["content"];
response.sendRedirect[request.getRequestURI[]];
}
}
2Nếu trình duyệt của bạn nhìn thấy một trong những biểu tượng này, nó biết rằng nội dung đó là một thẻ HTML, do đó nên được sử dụng để định dạng văn bản thay vì hiển thị cho người xemNhưng nếu chúng ta muốn văn bản của mình bao gồm ký hiệu
MyServlet
MyServlet
MyServlet
/home
3 hoặc
MyServlet
MyServlet
MyServlet
/home
4 thì sao? import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
if[!request.getParameter["content"].matches["[\\w*\\s*]*"]]{
request.setAttribute["error", "Please enter only letters, numbers, and spaces."];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
return;
}
this.content = request.getParameter["content"];
response.sendRedirect[request.getRequestURI[]];
}
}
6 mà không có phần import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
if[!request.getParameter["content"].matches["[\\w*\\s*]*"]]{
request.setAttribute["error", "Please enter only letters, numbers, and spaces."];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
return;
}
this.content = request.getParameter["content"];
response.sendRedirect[request.getRequestURI[]];
}
}
7 được phân tích dưới dạng HTML?Chúng ta cần thoát những ký tự này bằng các thực thể HTML. Các thực thể HTML là một chuỗi ký tự đặc biệt được hiển thị dưới dạng một ký tự và không được phân tích cú pháp dưới dạng thẻ HTML
3 hiển thị làMyServlet MyServlet MyServlet /home
3MyServlet MyServlet MyServlet /home
4 hiển thị làMyServlet MyServlet MyServlet /home
4MyServlet MyServlet MyServlet /home
2 hiển thị làUser Input Example
${error}
Content:
${content}
2User Input Example
${error}
Content:
${content}
4 hiển thị làUser Input Example
${error}
Content:
${content}
4User Input Example
${error}
Content:
${content}
6 hiển thị làUser Input Example
${error}
Content:
${content}
6User Input Example
${error}
Content:
${content}
Các thực thể
MyServlet
MyServlet
MyServlet
/home
3 và
MyServlet
MyServlet
MyServlet
/home
4 phù hợp để hiển thị nội dung dưới dạng văn bản thuần túy thay vì HTML cần được phân tích cú pháp. Thực thể
User Input Example
${error}
Content:
${content}
2 là cần thiết vì ký hiệu và dấu ____28_______2 bình thường được coi là phần đầu của thực thể [vì vậy nếu bạn muốn văn bản của mình hiển thị dưới dạng
MyServlet
MyServlet
MyServlet
/home
3 thay vì
MyServlet
MyServlet
MyServlet
/home
3, bạn phải sử dụng import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringEscapeUtils;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = StringEscapeUtils.escapeHtml4[request.getParameter["content"]];
response.sendRedirect[request.getRequestURI[]];
}
}
4]. Các thực thể
User Input Example
${error}
Content:
${content}
4 và
User Input Example
${error}
Content:
${content}
6 rất hữu ích khi bạn muốn đặt nội dung người dùng bên trong các thuộc tính phần tử [ví dụ: nếu bạn muốn thực hiện, điều gì sẽ xảy ra nếu
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringEscapeUtils;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = StringEscapeUtils.escapeHtml4[request.getParameter["content"]];
response.sendRedirect[request.getRequestURI[]];
}
}
7 chứa ký hiệu
User Input Example
${error}
Content:
${content}
4?]Vì vậy, nếu chúng tôi chỉ muốn hiển thị nội dung của người dùng chính xác như khi họ nhập nội dung đó mà không bị phân tích cú pháp thành HTML, thì chúng tôi chỉ cần thay thế bất kỳ ký hiệu nào có thể được phân tích cú pháp thành HTML hoặc can thiệp vào định dạng của chúng tôi bằng thực thể HTML tương ứng của chúng. Chúng ta có thể làm điều này bằng cách sử dụng các hàm
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringEscapeUtils;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = StringEscapeUtils.escapeHtml4[request.getParameter["content"]];
response.sendRedirect[request.getRequestURI[]];
}
}
9 và import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = Jsoup.clean[request.getParameter["content"], Whitelist.basic[]];
response.sendRedirect[request.getRequestURI[]];
}
}
0, nhưng thay vì phát minh lại bánh xe, hãy sử dụng một libary thực hiện việc này cho chúng taThư viện Apache Commons Lang cung cấp một số chức năng hữu ích để thoát khỏi nội dung. Tải xuống tệp
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = Jsoup.clean[request.getParameter["content"], Whitelist.basic[]];
response.sendRedirect[request.getRequestURI[]];
}
}
1 của thư viện và sao chép tệp đó vào thư mục import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = Jsoup.clean[request.getParameter["content"], Whitelist.basic[]];
response.sendRedirect[request.getRequestURI[]];
}
}
2 trong thư mục ứng dụng web của bạn. Bây giờ chúng ta có thể sử dụng thư viện đó trong servlet của mìnhimport java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringEscapeUtils;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = StringEscapeUtils.escapeHtml4[request.getParameter["content"]];
response.sendRedirect[request.getRequestURI[]];
}
}
Bây giờ, hàm doPost[]
sử dụng hàm
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = Jsoup.clean[request.getParameter["content"], Whitelist.basic[]];
response.sendRedirect[request.getRequestURI[]];
}
}
4 để thoát khỏi nội dung, hàm này hiển thị dưới dạng văn bản thuần túy thay vì nội dung HTMLPhương pháp thoát nội dung này rất hữu ích nếu bạn muốn có một trình soạn thảo văn bản rất cơ bản không cung cấp bất kỳ kiểu dáng nào và bạn muốn hiển thị văn bản chính xác như cách người dùng đã nhập nó
Nội dung làm sạch
Không phải tất cả các thẻ hoặc thuộc tính HTML đều nguy hiểm, vì vậy bạn có thể cho phép một số HTML, miễn là bạn không cho phép nội dung nguy hiểm. Ví dụ: bạn có thể muốn cho phép
và
- thẻ, nhưng không phải
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = Jsoup.clean[request.getParameter["content"], Whitelist.basic[]];
response.sendRedirect[request.getRequestURI[]];
}
}
5Bây giờ chúng tôi tải thư viện CKEditor, sau đó gọi hàm
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = Jsoup.clean[request.getParameter["content"], Whitelist.basic[]];
response.sendRedirect[request.getRequestURI[]];
}
}
6 để thay thế vùng văn bản cơ bản bằng vùng văn bản đa dạng thứcLưu ý rằng chúng tôi vẫn cần xử lý nội dung phía máy chủ, ngay cả khi chúng tôi đang sử dụng trình soạn thảo văn bản đa dạng thức. Điều này là để ngăn người dùng độc hại làm những việc như
- Tắt JavaScript và truy cập trang web của bạn để tắt xử lý phía máy khách
- Chỉnh sửa trang web của bạn bằng các công cụ dành cho nhà phát triển để tắt quá trình xử lý phía máy khách của bạn
- Tạo biểu mẫu HTML cơ bản của riêng họ để đăng lên máy chủ của bạn
- Sử dụng chương trình như cURL để đăng nội dung trực tiếp lên máy chủ của bạn
Vấn đề là, bạn không bao giờ nên tin tưởng bất kỳ nội dung nào đến từ phía khách hàng. Luôn thực hiện kiểm tra phía máy chủ
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = Jsoup.clean[request.getParameter["content"], Whitelist.basic[]];
response.sendRedirect[request.getRequestURI[]];
}
}
doPost[]
sử dụng danh sách trắng cơ bản của jSoup để đảm bảo chỉ cho phép HTML hợp lệ
Bây giờ nếu chúng tôi chạy máy chủ của mình, chúng tôi sẽ thấy trình soạn thảo văn bản đa dạng thức
Lưu ý rằng trình chỉnh sửa hiện có một thanh công cụ cho phép người dùng thay đổi định dạng của văn bản, được hiển thị trong trình chỉnh sửa WYSIWYG
Khi biểu mẫu được gửi, nội dung xuất hiện dưới dạng văn bản HTML thông thường, chúng tôi có thể xử lý chính xác cách chúng tôi xử lý văn bản HTML trong tất cả các ví dụ trên. Hiện tại, chúng tôi chỉ hiển thị nó trong trang
Có rất nhiều thư viện để hiển thị các trình chỉnh sửa trên máy khách và phân tích nội dung trên máy chủ, vì vậy bạn sẽ phải tìm một sự kết hợp phù hợp nhất với bạn và trang web của bạn
Thuộc tính và URL
Hãy nhớ rằng các URL và thuộc tính có giới hạn nội dung riêng
Ví dụ: HTML hoàn toàn có thể chứa ký tự dấu chấm hỏi
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = Jsoup.clean[request.getParameter["content"], Whitelist.basic[]];
response.sendRedirect[request.getRequestURI[]];
}
}
8, nhưng hãy nhớ rằng ký hiệu import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
public class MyServlet extends HttpServlet {
private String content = "There is no content yet.";
@Override
public void doGet[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
request.setAttribute["content", content];
request.getRequestDispatcher["WEB-INF/jsp/render.jsp"].forward[request,response];
}
@Override
public void doPost[HttpServletRequest request, HttpServletResponse response] throws ServletException, IOException {
this.content = Jsoup.clean[request.getParameter["content"], Whitelist.basic[]];
response.sendRedirect[request.getRequestURI[]];
}
}
8 trong URL đại diện cho tham số chuỗi truy vấn. Vì vậy, nếu bạn đang sử dụng tên người dùng do người dùng nhập và xây dựng các URL như doPost[]
0, điều gì sẽ xảy ra nếu người dùng đăng ký với tên doPost[]
1 và bạn đã sử dụng tên đó trong URL của mình? Hoặc nếu bạn đang xây dựng html như
, điều gì sẽ xảy ra nếu tên người dùng là doPost[]
2?
Vấn đề là, bạn phải suy nghĩ cẩn thận về chính xác cách bạn đang sử dụng nội dung. Các loại nội dung khác nhau có các loại hạn chế khác nhau và nội dung tốt ở nơi này có thể không ổn ở nơi khác
Chúng tôi đã thấy khá nhiều giải pháp cho vấn đề này. chúng tôi cần thoát khỏi nội dung bằng cách mã hóa nội dung đó thành các ký tự an toàn cho bất kỳ mục đích gì chúng tôi đang sử dụng
Bản tóm tắt
Có rất nhiều cách để phân tích cú pháp văn bản và không có một cách tiếp cận đúng nào. Những gì bạn chọn tùy thuộc vào bạn và cách bạn muốn trang web của mình hoạt động, nhưng quy trình chung mà bạn sẽ tuân theo là
- Quyết định loại nội dung bạn muốn chấp nhận
- Quyết định loại trình chỉnh sửa nào bạn muốn người dùng của mình tương tác. Xây dựng logic phía máy khách hoặc tìm thư viện tạo trình chỉnh sửa
- Viết mã Java [có thể sử dụng thư viện] để phân tích cú pháp đầu vào đó và lưu ý rằng những người dùng ác ý có thể dễ dàng vượt qua các hạn chế phía máy khách của bạn
- Hiển thị lại văn bản đã phân tích cú pháp trong trang web của bạn
Bạn có thể sẽ có sự kết hợp của các loại trình chỉnh sửa và hạn chế nội dung khác nhau. tên người dùng có thể có các giới hạn nội dung khác với nội dung của bài đăng, có thể có các giới hạn nội dung khác với nhận xét
Hãy chắc chắn rằng bạn thực hiện rất nhiều thử nghiệm đầu vào của người dùng. Hãy thử phá cách với những ký tự lạ. Hãy thử phá vỡ nó bằng cách tiêm HTML và JavaScript. Tốt hơn là dành vài giờ để đảm bảo mọi thứ hoạt động ngay bây giờ hơn là dành nhiều thời gian để khắc phục thiệt hại sau khi hoàn thành
Bài tập về nhà
Hãy thử nhập HTML vào một số trang web mà bạn sử dụng. Họ có những hạn chế gì?
Nhiều trang web [GitHub, Twitter, Facebook và Google, v.v.] cung cấp phần thưởng nếu bạn tìm thấy lỗ hổng XSS. Google “phần thưởng lỗ hổng xss” nếu điều này nghe có vẻ thú vị với bạn
Phương thức nhập yêu thích của cá nhân tôi là Markdown. Tìm thư viện JavaScript hiển thị bản xem trước Markdown và tìm thư viện Java phân tích nội dung trên máy chủ
Tìm một trình chỉnh sửa mà bạn thích và thêm nó vào trang web của bạn. Đảm bảo bạn thực thi các hạn chế nội dung trên máy chủ
Công dụng của HTML Sanitizer là gì?
API HTML Sanitizer cho phép nhà phát triển lấy các chuỗi đối tượng HTML và Document hoặc DocumentFragment không đáng tin cậy, đồng thời khử trùng chúng để chèn an toàn vào DOM của tài liệu.Tôi có nên vệ sinh đầu vào của người dùng không?
Làm sạch đầu vào có thể là một lựa chọn tốt khi định dạng đầu vào không nghiêm ngặt nhưng vẫn có thể dự đoán được phần nào , chẳng hạn như số điện thoại hoặc các trường văn bản tự do khác. Có một số cách khác nhau để làm sạch đầu vào, bạn có thể sử dụng danh sách trắng, danh sách đen hoặc đầu vào thoát.Vệ sinh HTML nghĩa là gì?
Trong dọn dẹp dữ liệu, dọn dẹp HTML là quá trình kiểm tra tài liệu HTML và tạo tài liệu HTML mới chỉ giữ lại bất kỳ thẻ nào được chỉ định là "an toàn" và mong muốn.Tại sao việc khử trùng dữ liệu đầu vào trước khi xử lý lại quan trọng?
Việc không làm sạch đầu vào có thể dẫn đến việc kẻ tấn công đưa mã SQL vào đầu vào biểu mẫu để chúng có thể thực hiện bất kỳ điều thú vị nào, từ xóa thông tin khỏi cơ sở dữ liệu đến tiêm thông tin