Khi làm việc với các ứng dụng cần bảo mật thì bắt buộc các bạn phải biết đến 2 khái niệm authentication và authorization. Nói nôm na thì authentication liên quan đến việc ai được quyền sử dụng ứng dụng còn authorization liên quan đến việc những resource nào, những phần nào của ứng dụng mà các bạn được phép sử dụng. Đối với các ứng dụng web có sử dụng Spring framework thì các bạn có thể sử dụng Spring Security để hiện thực 2 khái niệm này. Cụ thể nó như thế nào? Chúng ta sẽ bắt đầu tìm hiểu về Spring Security trong bài viết này các bạn nhé!
Đầu tiên, mình sẽ tạo mới một ứng dụng Spring MVC để làm ví dụ các bạn nhé:
Để làm việc với Spring Security, các bạn cần khai báo dependency spring-security-web và spring-security-config như sau:
1 2 3 4 5 6 7 8 9 10 |
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${org.springframework.security-version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${org.springframework.security-version}</version> </dependency> |
với:
1 2 3 4 |
<properties> ... <org.springframework.security-version>6.0.2</org.springframework.security-version> </properties> |
Hiện tại khi chạy ứng dụng, các bạn sẽ thấy kết quả như sau:
Để làm ví dụ cho phần authentication với Spring Security, mình sẽ thêm code để bắt buộc người dùng, muốn xem được trang trên, họ phải đăng nhập sử dụng username và password.
Nhưng trước tiên, mình cần nói với các bạn là: chúng ta có 2 cách để hiện thực Spring Security, một là sử dụng tập tin cấu hình và cách thứ hai là sử dụng các Java annotation mà Spring Security hỗ trợ.
Ok, quay trở lại với ví dụ của chúng ta, mình sẽ sử dụng tập tin cấu hình để hiện thực Spring Security. Để làm được điều này, các bạn hãy tạo mới một tập tin cấu hình cho Spring Security tên là security.xml nằm trong thư mục src/main/webapp/WEB-INF/spring. Tập tin này sẽ định nghĩa các bean cần thiết của Spring Security trong Spring container. Nội dung của tập tin này như sau:
1 2 3 4 5 6 7 8 9 10 11 12 |
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd"> <http /> <user-service> <user name="khanh" password="{noop}123456" authorities="ROLE_USER" /> </user-service> </beans:beans> |
Khai báo <http > là khai báo quan trọng, Spring sẽ khởi tạo các bean cần thiết của Spring Security dựa vào khai báo của thẻ này các bạn nhé! Ở đây, vì chúng ta chỉ cần enable chức năng authentication của Spring Security cho ứng dụng của mình nên các bạn chỉ cần khai báo như thế!
Khai báo <user-service> cho phép chúng ta có thể tạo mới thông tin user in-memory dùng để authenticate vào ứng dụng của chúng ta. Chúng ta có thể khai báo thông tin user sử dụng một tập tin .properties hoặc sử dụng tag <user> như trong ví dụ của mình để tạo in-memory user. Tất nhiên, chúng ta còn có thể khai báo để lấy thông tin user từ các nguồn khác nữa như database chẳng hạn. Để đơn giản, mình đã sử dụng in-memory user để giới thiệu với các bạn trong bài viết này.
Trong khai báo thông tin user, như các bạn thấy, chúng ta cũng sẽ cần phải khai báo role của user sử dụng attribute authorities, cái này được sử dụng cho phần authorization. Phần password, thật ra password mình khai báo chỉ là “123456” mà thôi, chữ “{noop}” có một ý nghĩa khác liên quan đến password encoder, mình sẽ đề cập rõ hơn trong những bài viết sau các bạn nhé!
OK, vậy là chúng ta đã có tập tin cấu hình cơ bản cần phải có của một ứng dụng Spring Security. Chúng ta cần phải khai báo tập tin cấu hình này với web servlet trong tập tin web.xml của ứng dụng.
Các bạn hãy mở tập tin web.xml và thêm vào những dòng sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!-- Spring Security Filter --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Loads Spring Security Configuration File --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/security.xml</param-value> </context-param> |
Phần khai báo <context-param> với thông tin về tập tin security.xml thì dùng để thêm các bean được định nghĩa trong tập tin này vào servlet của chúng ta.
Ở đây, chúng ta còn có thể phần khai báo <filter>, mục đích của việc khai báo này nói nôm nay thì để làm interceptor cho các request của người dùng đến ứng dụng của chúng ta. Chỉ những request nào pass được interceptor thì mới có thể access được ứng dụng. Các bạn có thể tìm hiểu thêm về tag <filter> trong tập tin web.xml để hiểu thêm nhé! Class org.springframework.web.filter.DelegatingFilterProxy của Spring Security sẽ là class handle các request để đảm bảo rằng, chúng thoả điều kiện mà chúng ta định nghĩa trong tập tin security.xml.
Bây giờ, nếu chạy lại ứng dụng, các bạn sẽ thấy ứng dụng của chúng ta lúc này sẽ xuất hiện một trang bắt chúng ta phải đăng nhập như sau:
Đây là trang mặc định của Spring Security đấy các bạn! Nhập thông tin mà chúng ta đã khai báo trong tập tin security.xml, rồi nhấn “Sign in”, các bạn sẽ access được vào ứng dụng của chúng ta.
Vậy là xong phần authentication rồi đó các bạn!
Để enable chức năng authorization, các bạn cần modify tập tin security.xml để thêm một số cấu hình khác như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd"> <http auto-config="true"> <intercept-url pattern="/" access="hasRole('ROLE_USER')"/> </http> <user-service> <user name="khanh" password="{noop}123456" authorities="ROLE_USER" /> <user name="thanh" password="{noop}123456" authorities="ROLE_GUEST" /> </user-service> </beans:beans> |
Ở đây, mình đã thêm một user khác “thanh” với role là ROLE_GUEST và mình đã modify tag <http> để thêm một intercept-url cho request tới địa chỉ “http://localhost:8080/” là chỉ dành cho user với role ROLE_USER. Điều này có nghĩa chỉ user nào có role là ROLE_USER mới có quyền truy cập tới địa chỉ “http://localhost:8080/”.
Nếu bây giờ, các bạn chạy lại ứng dụng và đăng nhập với user “thanh” với thông tin đăng nhập như trên, các bạn sẽ thấy kết quả như sau:
Như các bạn thấy, mặc dù user “thanh” có quyền access vào ứng dụng của chúng ta nhưng cho resource với đường dẫn “/”, user này không có quyền truy cập.
Thử lại với user “khanh”, các bạn sẽ thấy việc access tới trang “http://localhost:8080/” là bình thường cho user này.
Rất hay phải không các bạn?
Long
Ui cảm ơn anh nhiều vì bài viết! Rất hữu ích và chi tiết luôn.
Em đang học về Spring mà nhiều nguồn ko giải thích về phần config.
Giờ giải ngố được kha khá rồi hehe.