Hướng dẫn bảo mật ứng dụng Spring Boot với Spring Security và JWT
Bài viết này sẽ giúp bạn hiểu cách bảo mật ứng dụng Spring Boot bằng việc sử dụng Spring Security kết hợp với JSON Web Token (JWT). Mặc dù bài viết có độ dài tương đối, mình đã chia thành các mục cụ thể để dễ theo dõi và hiểu rõ hơn. Cuối bài viết, bạn sẽ tìm thấy mã nguồn để tham khảo. Hãy cùng bắt đầu!
1. Tìm hiểu về JSON Web Token (JWT)
1.1 JWT là gì?
JSON Web Token (JWT) là một tiêu chuẩn mở (RFC 7519) định nghĩa cách truyền tải thông tin an toàn giữa các bên như một đối tượng JSON. Thông tin này có thể được xác minh và tin cậy vì nó được ký số. JWT có thể được ký bằng một khóa bí mật (sử dụng thuật toán HMAC) hoặc bằng một cặp khóa công khai/riêng tư sử dụng RSA hoặc ECDSA.
- Compact and self-contained: JWT nhẹ và độc lập hơn so với SWT hay SAML.
- JSON object: Bản chất JWT là một chuỗi các đối tượng JSON được mã hóa.
- Ký bằng khóa bí mật hoặc cặp khóa công khai/riêng tư: Đảm bảo tính toàn vẹn và bảo mật của dữ liệu.
1.2 Cấu trúc của JWT
Một chuỗi JWT bao gồm 3 phần, được phân tách bằng dấu chấm (.) như sau:
[Header].[Payload].[Signature]
- Header: Chứa thông tin loại token và thuật toán ký.
- Payload: Chứa thông tin (claims) về đối tượng truy cập hệ thống và thông tin bổ sung.
- Signature: Tạo signature bằng cách sử dụng header, payload, secret key và thuật toán ký.
1.3 Cách hoạt động của JWT
Hệ thống sử dụng xác thực dựa trên token sẽ phát một JWT cho người dùng sau khi đăng nhập thành công. Người dùng sẽ đính kèm JWT này trong phần header của các request tiếp theo, thường theo dạng:
Authorization: Bearer <JWT>
Hệ thống sử dụng JWT để xác thực và phân quyền người dùng truy cập tài nguyên, dịch vụ và API của hệ thống.
2. Cài đặt và cấu hình ứng dụng Spring Boot
Để khởi tạo ứng dụng Spring Boot, bạn có thể truy cập Spring Initializr và chọn các dependencies cần thiết, sau đó bấm GENERATE và nhập vào IDE của bạn.
Các dependencies trong file pom.xml
:
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Cấu hình kết nối cơ sở dữ liệu:
properties
spring.datasource.url=jdbc:mariadb://localhost:3306/<database>?useSSL=false
spring.datasource.username=<username>
spring.datasource.password=<password>
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect
spring.jpa.hibernate.ddl-auto=update
3. Thêm dependencies cho JWT và Spring Security
Để cấu hình Spring Security và JWT, bạn cần thêm các dependencies sau vào file pom.xml
:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>
4. Cấu hình Spring Security và JWT
4.1 Định nghĩa UserDetails
Tạo class UserDetailsImpl
để cung cấp thông tin chi tiết về người dùng cho quá trình xác thực.
4.2 Implement UserDetailsService
Tạo class UserDetailsServiceImpl
để truy xuất thông tin người dùng từ cơ sở dữ liệu.
4.3 Tạo JWT Utils
Cung cấp các phương thức để tạo, xác minh và trích xuất thông tin từ JWT.
4.4 Xử lý ngoại lệ
Tạo AuthEntryPointJwt
để xử lý các trường hợp không được phép truy cập.
4.5 Tạo filter cho xác thực
Tạo class AuthTokenFilter
để xác thực người dùng mỗi khi có request đến ứng dụng.
4.6 Cấu hình WebSecurity
Sử dụng class WebSecurityConfig
để cấu hình Spring Security cho toàn bộ ứng dụng.
5. Đăng ký tài khoản (SignUp)
5.1 Luồng đăng ký
- Kiểm tra thông tin người dùng.
- Tạo đối tượng
User
và lưu vào cơ sở dữ liệu. - Trả về kết quả cho client.
5.2 Xử lý ngoại lệ toàn cục
Tạo GlobalExceptionHandler
để xử lý các exception phát sinh trong quá trình đăng ký.
5.3 Kiểm tra đăng ký
Thực hiện các test case cho chức năng đăng ký để đảm bảo rằng mọi thứ hoạt động đúng như mong đợi.
6. Đăng nhập (SignIn)
6.1 Luồng đăng nhập
- Kiểm tra thông tin đăng nhập và tạo JWT nếu thông tin hợp lệ.
6.2 Kiểm tra đăng nhập
Thực hiện các test case cho chức năng đăng nhập và đảm bảo rằng người dùng có thể lấy được JWT.
7. Truy cập tài nguyên với JWT
7.1 Kiểm tra phân quyền
Tạo các endpoint của TestController
và kiểm tra quyền truy cập dựa trên role.
7.2 Kiểm tra truy cập
Sử dụng các test case để kiểm tra quyền truy cập của người dùng với JWT.
8. Kết luận
Bài viết này đã hướng dẫn chi tiết cách bảo mật ứng dụng Spring Boot bằng Spring Security và JWT. Hy vọng bạn sẽ tìm thấy các thông tin hữu ích. Đừng quên xem mã nguồn hoàn chỉnh ở cuối bài viết để tham khảo thêm!
source: viblo