Khi nào bạn nên dọn dẹp HTML?

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ày

Khi nào bạn nên dọn dẹp HTML?

Bạn có thể nhập một số văn bản để đảm bảo nó hoạt động

Khi nào bạn nên dọn dẹp HTML?

Ở đâ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

Khi nào bạn nên dọn dẹp HTML?

Đ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
  

0

Cho 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
  

1

trở 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ẻ HTML
  • Làm sạch nội dung để chỉ cho phép HTML an toàn thông qua

    
    
      
        MyServlet
        MyServlet
      
      
        MyServlet
        /home
      
    
    
    7

    trở thành
    
    
      
        MyServlet
        MyServlet
      
      
        MyServlet
        /home
      
    
    
    8
  • Tách nội dung để không cho phép bất kỳ HTML nào

    
    
      
        MyServlet
        MyServlet
      
      
        MyServlet
        /home
      
    
    
    7

    trở thành
    
    
    	
    		User Input Example
    	
    	
    		

    Content:


    ${content}



    4
  • Thay 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ày
  • Cá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 qua

    Bây giờ JSP chỉ hiển thị lỗi nếu nó xuất hiện

    
    
    	
    		User Input Example
    	
    	
    		<% if(request.getAttribute("error") != null){ %>
    			

    ${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 quy

    Cá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 HTML

    thoá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ư trong

    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());
    	}
    }
    
    2

    Nế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 xem

    Như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

    • 
      
        
          MyServlet
          MyServlet
        
        
          MyServlet
          /home
        
      
      
      3 hiển thị là
      
      
        
          MyServlet
          MyServlet
        
        
          MyServlet
          /home
        
      
      
      3
    • 
      
        
          MyServlet
          MyServlet
        
        
          MyServlet
          /home
        
      
      
      4 hiển thị là
      
      
        
          MyServlet
          MyServlet
        
        
          MyServlet
          /home
        
      
      
      4
    • 
      
      	
      		User Input Example
      	
      	
      		<% if(request.getAttribute("error") != null){ %>
      			

      ${error}

      <% } %>

      Content:


      ${content}



      2 hiển thị là
      
      
      	
      		User Input Example
      	
      	
      		<% if(request.getAttribute("error") != null){ %>
      			

      ${error}

      <% } %>

      Content:


      ${content}



      2
    • 
      
      	
      		User Input Example
      	
      	
      		<% if(request.getAttribute("error") != null){ %>
      			

      ${error}

      <% } %>

      Content:


      ${content}



      4 hiển thị là
      
      
      	
      		User Input Example
      	
      	
      		<% if(request.getAttribute("error") != null){ %>
      			

      ${error}

      <% } %>

      Content:


      ${content}



      4
    • 
      
      	
      		User Input Example
      	
      	
      		<% if(request.getAttribute("error") != null){ %>
      			

      ${error}

      <% } %>

      Content:


      ${content}



      6 hiển thị là
      
      
      	
      		User Input Example
      	
      	
      		<% if(request.getAttribute("error") != null){ %>
      			

      ${error}

      <% } %>

      Content:


      ${content}



      6

    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
    	
    	
    		<% if(request.getAttribute("error") != null){ %>
    			

    ${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
    	
    	
    		<% if(request.getAttribute("error") != null){ %>
    			

    ${error}

    <% } %>

    Content:


    ${content}



    4 và
    
    
    	
    		User Input Example
    	
    	
    		<% if(request.getAttribute("error") != null){ %>
    			

    ${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
    	
    	
    		<% if(request.getAttribute("error") != null){ %>
    			

    ${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 ta

    Thư 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ình

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

    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 HTML

    Khi nào bạn nên dọn dẹp HTML?

    Phươ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

      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());
      	}
      }
      
      5

    Bâ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ức

    Lư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

    Khi nào bạn nên dọn dẹp HTML?

    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

    Khi nào bạn nên dọn dẹp HTML?

    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