Thứ Tư, 19 tháng 7, 2017

Sử dụng Filter kết hợp với Struts 2 Framework để xác thực và phân quyền truy cập cho user

Sử dụng Filter kết hợp với Struts 2 Framework để xác thực và phân quyền truy cập cho user

 

Tác giả: Bạch Minh Nam

 

Mục đích: Chủ đề của bài viết này hướng dẫn cách sử dụng Filter kết hợp với Struts 2 Framework để lọc quyền truy cập vào các resource khác nhau tùy theo vai trò của user khi login vào hệ thống.

 

Yêu cầu kiến thức cơ bản:

  • Nắm rõ mô hình MVC2, Struts 1.x Framework, các khái niệm cơ bản của Struts 2.x Framework
  • Nắm rõ những phương pháp cơ bản của lập trình hướng đối tượng bằng ngôn ngữ Java
  • Nắm rõ những khái niệm lập trình web sử dụng JavaEE cùng những kiến thức về Servlet, JSP
  • Nắm vững cơ chế vận hành của RequestDispatcher và Filter, cách sử dụng Filter như là Controller trong mô hình MVC2 (có thể xem thêm bài viết về Filter tại đây: http://www.kieutrongkhanh.net/2017/06/topic-su-dung-filter-nhu-la-controller.html)

 

Mô tả ứng dụng:

  • Ứng dụng yêu cầu đăng nhập vào hệ thống với username và password được cung cấp

 

 

  • Nếu thành công với role = 1 (staff) thì hệ thống sẽ tự động chuyển đến trang search dành cho staff. Ngược lại, hệ thống sẽ chuyển sang trang invalid

 

  • Khi đăng nhập với phân quyền là staff, statff được phép search sản phẩm theo tên hoặc ID

  • Sau khi logout khỏi hệ thống, nếu người sử dụng back trình duyệt để trợ lại trang search, hoặc copy paste một đường link bất kì (book mark) để truy cập trang mà họ không có quyền truy cập, thì ứng dụng sẽ chuyển đến trang “Không tìm thấy” – page not found.

  • Database được sử dụng trong bài viết này có tên MobileStore. Cấu trúc của Database được mô tả như bên dưới

  • Dữ liệu mẫu nhập được sử dụng để demo (role = 1: staff) như sau

 

 

 

  • Yêu cầu tool sử dụng:

o   IDE: Netbeans 6.9.1, Netbeans 7.4 hoặc Netbeans 8.x

o   JDK 6 update 22, JDK 7 update 51, JDK 8 update 66

o   Server: Tomcat 6.0.26, Tomcat 7.x, Tomcat 8.x

o   DBMS: SQL Server 2005 đến SQL Server 2014

o   Thư viện hỗ trợ: Driver kết nối database SQLServer (sqljdbc.jar hay sqljdbc4.jar), Struts2 Framework taglib

o   IDE Netbeans phải cài đặt plugin hỗ trợ Struts 2 Framework

 

Các bước thực hiện:

  • Tạo mới project Web Application với JavaEE5, server Apache Tomcat, thư viện Framework Strut 2
  • Thực hiện cấu hình Datasource kết nối DB động

 

 

 

 

  • Chúng ta bắt đầu thực hiện chức năng login

o   Tạo trang login

 

 

o   Mapping default page cho trang login với welcome file trong tập tin web.xml là rỗng và cấu hình trong tập tin struts.xml như sau

 

 

o   Tạo trang invalid, với đường link quay về default page

 

 

o   Lưu ý:

§  Với một vài hệ thống, việc để href=“” (chuỗi rỗng) sẽ load trở lại chính đường link hiện tại trên khung URL của browser, do đó, để gọi lại action “rỗng” để quay về default page, chúng ta sẽ để cặp dấu nháy đơn bọc trong cặp dấu nháy kép: href= “‘’”

o   Tạo DTO để chứa thông tin của user khi login vào hệ thống mapping với bảng tbl_Account

 

o   Tạo DAO với function checkLogin, kiểm tra đăng nhập với role = 1 (staff)

o   Lưu ý:

§  Trường password được set là chuỗi rỗng “” nếu như đã xác thực người sử dụng là staff nhằm đảm bảo tính bảo mật của dữ liệu người dùng khi được lưu trữ trên session

§  Hàm checkLogin chỉ kiểm tra những account nào có role = 1

o   Tạo Action Class để Login:

o   Tạo trang search.jsp sơ khởi:

 

o   Mapping action login vào struts.xml

 

 

o   Clean, build và deploy để test thử ứng dụng

o   Chúng ta hoàn thành xong chức năng Login

 

  • Chúng ta chuyển đến thực hiện chức năng search theo tên hoặc theo ID của sản phẩm

o   Tạo đối tượng DTO để đón nhận dữ liệu mapping khi search thành công

 

o   Tạo DAO với chức năng search theo tên hoặc theo ID của sản phẩm:

 

 

o   Tạo Action Class xử lý chức năng search:

§  Điều kiện !searchValue.trim().equals(“”) là để Action không search khi chuỗi giá trị bằng rỗng hoặc chỉ chứa khoảng trắng.

 

 

o   Mapping action search vào tập tin struts.xml

 

 

o   Cập nhật giao diện của trang search.jsp

§  Import Taglib của Struts 2 Framework

§  Tạo search form

 

 

§  Tạo grid để hiển thị kết quả search

§  Lưu ý: trong phần kiểm tra điều kiện, chúng ta nên để thêm giá trị “searchValue!=null” nhằm mục đích đảm bảo trang search.jsp được load lần đầu tiên, sẽ không xuất hiện dòng “No result found!!”.

 

 

o   Clean build và deploy, thấy được kết quả search

o   Chúng ta hoàn thành xong chức năng search

  • Chúng ta tiếp tục thực hiện chức năng Logout

o   Chúng ta thực hiện cập nhật nội dung trang search.jsp với đường link Logout

 

o   Tạo Logout Action

 

o   Mapping action logout vào file struts.xml

o   Clean, build và deploy, thấy nút logout hoạt động như mong đợi (chuyển về trang login.html)

o   Chúng ta hoàn thành xong chức năng logout.

 

  • Bây giờ chúng ta sẽ tự tạo và sử dụng Filter như là một lớp xác thực bảo mật khi đăng nhập.

o   Đầu tiên, chúng ta thực hiện tạo trang notFoundPage.html

o   Sau đó, chúng ta thực hiện tạo mới filter AuthFilter lưu trong thư mục sample/filter của Source Package

o   Nhấn next.

o   Lưu ý: trong bảng Filter Mapping, khi AuthFilter của chúng ta nằm trên cùng, nghĩa là tất cả mọi request đến Web App đều phải qua filter này trước tiên trước khi chuyển vào FilterDispatcher của Struts2 Framework. (Mặc định khi tạo mới, filter sẽ nằm trên cùng)

o   Nhấn nút Finish.

o   Chúng ta tiến hành cài đặt code cho AuthFilter:

§  Tạo list danh sách các resource được phép truy cập dành cho mỗi role tương ứng trong Web App

§  List “guest” chứa những resource mà mọi đối tượng không cần đăng nhập vẫn có thể xem thấy: bao gồm các trang như login.html, invalid.html, notFoundPage.html; và bao gồm các action như action rỗng dẫn đến default page ban đầu, action login…

§  List “staff” chứa những resource phải đăng nhập với tư cách staff mới có quyền truy cập: bao gồm trang như search.jsp, và các action như action search, action logout…

§  Lưu ý

o   Các action thường được gọi theo một trong hai cách là <tên action> hoặc là <tên action>.action, do đó, khi add một action vào list resource, chúng ta add một cặp như trên.

o   Ngoài ra, các thành phần resource để làm cho thực tế thì tên các page hay resource, chúng ta có thể mapping qua tập tin properties để mang tính linh hoạt khi thay đổi cho ứng dụng (tham khảo bài viết tại địa chỉ http://www.kieutrongkhanh.net/2016/12/xay-dung-ung-dung-voi-ejb-3-tren-entity.html )

§  Toàn bộ code vận dụng, chúng ta sẽ viết tập trung vào method doFilter

§  Đầu tiên kiểm tra trong session xem có login chưa, nếu chưa thì kiểu tra resource có chứa trong danh sách dành cho guest hay không, nếu có thì chuyển tới resource đó, nếu không thì chuyển đến trang 404 not found.

§  Tương tự, nếu đã login thì kiểm tra xem role của user là bao nhiêu, nếu role là staff và resource có trong danh sách cho phép của staff thì chuyển đến resource đó, nếu không thì chuyển về trang chủ dành cho staff là search.jsp

§  Dựa trên nhu cầu và thiết kế của Web App, chúng ta có thể tạo ra nhiều list resource tương ứng với mỗi một role cần phân quyền khác nhau, sau đó check role + resource tương tự như của staff trong hình mô tả.

o   Clean build deploy project, chúng ta hoàn thành xong chức năng của Filter trong việc xác minh user và phân quyền dựa trên role tương ứng.

  • Cấu trúc thư mục project sau khi hoàn tất các chức năng trên như sau:

 

 

Chúc mừng quí vị đã hoàn tất việc kết hợp Filter với một Framework, ở đây là Struts 2. Ở đây, chúng ta thấy rõ việc kết hợp việc kiến thức nền của việc xây dựng ứng dụng web, kết hợp design Pattern cùng với các Framework sẽ tăng tính linh hoạt và đa dạng trong xây dựng ứng dụng. Rất mong quí vị góp ý về nội dung bài viết này

4 nhận xét:

  1. e làm theo như a mà phần filter ko phân quyền đc ạ :((((

    Trả lờiXóa
  2. phần fillter không phân quyền được ở chổ getSession(false), lần đầu get thì bằng null nhưng lần sau nó tự tạo ra 1 session mới mặc dù đã set false

    Trả lờiXóa
    Trả lời
    1. Sau lần login đầu tiên thì một session sẽ được tạo ra, nên mặc dù getSession(false), nó vẫn sẽ trả về khác null.
      Tuy nhiên, trong hàm execute của LogoutAction, chúng ta đã remove attribute "USER". Nên theo nguyên tắc, nếu bạn code đúng, filter vẫn hoạt động chính xác.
      Hãy thử kiểm tra lại code. Nếu vẫn không được, hãy thử thay session.remove("USER"); bằng session.invalidate();
      Thân ái

      Xóa