🀄JWT + Spring Security Oauth
Trong bài viết này, chúng ta sẽ thảo luận về cách triển khai Spring Security OAuth2 để sử dụng JSON web Token.
OAuth2 Authorization Server
Trước đây, Spring Security OAuth cung cấp khả năng thiết lập Authorization Server như một Spring Application. Sau đó, chúng ta phải cài đặt cấu hình để nó sử dụng JwtTokenStore để chúng ta có thể sử dụng JWT tokens.
Tuy nhiên, OAuth đã bị từ chối bởi Spring và bây giờ chúng ta sẽ sử dụng Keycloak làm Authorization Server của mình.
Vì vậy, lần này, chúng ta sẽ thiết lập Authorization Server của mình dưới dạng Keycloak server được nhúng trong ứng dụng Spring Boot. Nó phát hành JWT tokens theo mặc định, vì vậy chúng ta hoàn toàn không cần cài đặt hay thay đổi cấu hình nữa.
Resource Server
Bây giờ, chúng ta hãy xem cách cấu hình Resource Server để sử dụng JWT.
Chúng ta sẽ thực hiện việc này trong file application.yml:
JWT chứa tất cả thông tin trong Tokens. Vì vậy, Resource Server cần xác minh Token để đảm bảo dữ liệu không bị sửa đổi. Thuộc tính jwk-set-uri chứa public key mà máy chủ có thể sử dụng cho mục đích này.
Thuộc tính issuer-uri trỏ đến Authorization Server URI, URI này cũng có thể được sử dụng để xác minh xác nhận quyền sở hữu Iss, như một biện pháp bảo mật bổ sung.
Ngoài ra, nếu thuộc tính jwk-set-uri không được thiết lập. Resource Server sẽ cố gắng sử dụng issuer-ui để xác định vị trí của key này, từ Authorization Server metadata endpoint..
Quan trọng hơn, việc thêm thuộc tính cho issuer-uri sẽ quyết định việc chúng ta phải chạy Authorization Server trước khi có thể khởi động Resource Server application.
Bây giờ hãy xem làm cách nào chúng ta có thể cấu hình JWT bằng cách sử dụng Java:
Ở đây, chúng ta đang ghi đè cấu hình Http Security mặc định. Vì vậy, chúng ta cần chỉ định rõ ràng rằng chúng ta muốn nó hoạt động như một Resource Server và rằng chúng tôi sẽ sử dụng Access Tokens có định dạng JWT bằng cách sử dụng các phương thức oauth2ResourceServer() và jwt() tương ứng.
Cấu hình JWT ở trên là những gì phiên bản Spring Boot mặc định đang cung cấp cho chúng ta. Điều này cũng có thể được tùy chỉnh như chúng ta sẽ thấy trong phần sau của bài viết.
Tùy chỉnh Claims bên trong Token
Bây giờ chúng ta hãy thiết lập một số cơ sở hạ tầng để có thể thêm một vài tùy chỉnh Claims trong Access Token do Authorization Server trả về. Các Claims tiêu chuẩn được cung cấp bởi framework đều có thể sử dụng rất tốt, nhưng hầu hết thời gian, chúng ta sẽ cần một số thông tin bổ sung trong token để sử dụng ở phía Client.
Hãy lấy ví dụ về một claim tùy chỉnh, organization, sẽ chứa tên tổ chức của người dùng nhất định.
Cấu hình Authorization Server
Đối với điều này, chúng tacần thêm một vài cấu hình vào file đị nghĩa realm, baeldung-domains.json:
Thêm organization vào người dùng john@test.com
Thêm protocolMapper được gọi là organization vào tùy chỉnh của jwtClient
Đối với thiết lập Keycloak, bạn cũng có thể thực hiện việc này bằng việc sử dụng Admin console.
Ngoài ra, điều quan trọng cần nhớ là cấu hình JSON ở trên dành riêng cho Keycloak và có thể khác với các máy chủ OAuth khác.
Khi cấu hình mới này được thiết lập và chạy, chúng ta sẽ nhận được thêm một thuộc tính organization = baeldung, trong token payload cho john@test.com:
Sử dụng Access Token trong Angular Client
Tiếp theo, chúng ta sẽ sử dụng thông tin của Token trong ứng dụng Angular Client. Chúng ta sẽ sử dụng thư viện angle2-jwt để làm việc đó.
Chúng ta cũng sẽ sử dụng organization claim trong AppService của mình và thêm một hàm getOrganization như sau:
Hàm này sử dụng JwtHelperService từ thư viện angle2-jwt để giải mã Access Token và nhận claim tùy chỉnh của chúng ta. Bây giờ tất cả những gì chúng ta cần làm là hiển thị nó trong AppComponent của mình:
Truy cập Extra Claims trong Resource Server
Nhưng, làm thế nào để chúng ta có thể truy cập thông tin đó ở phía Resource Server?
Truy cập Authentication Server Claims
Điều đó thực sự rất đơn giản: chúng ta chỉ cần giải nén nó từ org.springframework.security.oauth2.jwt.Jwt‘s AuthenticationPrincipal, như chúng ta sẽ làm đối với bất kỳ thuộc tính nào khác trong UserInfoController:
Cài đặt Add/Remove/Rename Claims
Bây giờ, điều gì sẽ xảy ra nếu chúng ta muốn thêm nhiều claim hơn ở phía Resource Server? Hoặc loại bỏ, đổi tên một số claim có sẵn?
Giả sử chúng ta muốn sửa đổi organization claim đến từ Authentication Server để nhận giá trị bằng chữ hoa. Ngoài ra, nếu claim không có trên phía người dùng, chúng ta cần đặt giá trị của nó là unknown.
Để đạt được điều này, trước tiên, chúng ta sẽ phải thêm một class thứ sẽ triển khai giao diện Converter và sử dụng MappedJwtClaimSetConverter để thay đổi các claim:
Sau đó, trong class SecurityConfig, chúng ta cần thêm instance JwtDecoder của riêng mình để ghi đè phiên bản được cung cấp bởi Spring Boot và đặt OrganizationSubClaimAdapter của chúng ta làm trình chuyển đổi claims:
Bây giờ khi chúng ta gọi API /user/info cho người dùng mike@other.com, chúng ta sẽ nhận được organization là UNKNOWN.
Lưu ý rằng việc ghi đè JwtDecoder mặc định được cấu hình bởi Spring Boot nên được thực hiện cẩn thận để đảm bảo tất cả các cấu hình cần thiết vẫn chuẩn xác.
Tải Keys từ Java Keystore
Trong cấu hình trước đây, chúng ta đã sử dụng public key mặc định của Authorization Server để xác minh tính toàn vẹn của token.
Chúng ta cũng có thể sử dụng keypair và chứng chỉ được lưu trữ trong Java Keystore file để thực hiện quá trình ký.
Tạo file JKS Java KeyStore
Đầu tiên, hãy tạo các keys - và cụ thể hơn là tệp .jks - bằng cách sử dụng công cụ dòng lệnh keytool:
Lệnh sẽ tạo một file có tên mytest.jks chứa các keys của chúng ta - cả public và private key, đồng thời đảm bảo keypass và storepass giống nhau.
Export Public Key
Tiếp theo, chúng ta cần Export Public Key của mình từ JKS đã tạo, chúng ta có thể sử dụng lệnh sau để làm như vậy:
Response trả về sẽ trông từa tựa như sau:
Tùy chỉnh Maven
Tiếp theo, chúng ta không muốn tệp JKS được chọn bởi quá trình lọc maven - vì vậy chúng ta sẽ đảm bảo loại trừ nó trong pom.xml:
Nếu chúng ta đang sử dụng Spring Boot, chúng ta cần đảm bảo rằng tệp JKS của chúng ta được thêm vào classpath của ứng dụng thông qua Plugin Spring Boot Maven - addResources:
Authorization Server
Bây giờ, chúng ta sẽ cấu hình Keycloak để sử dụng Keypair từ mytest.jks, bằng cách thêm nó vào phần KeyProvider của tệp JSON định nghĩa realm như sau:
Ở đây, chúng ta đã đặt mức độ ưu tiên là 101, lớn hơn bất kỳ Keypair nào khác cho Authorization Server và đặt active thành true. Điều này được thực hiện để đảm bảo rằng Authorization Server sẽ chọn Keypair cụ thể này từ thuộc tính jwk-set-uri mà chúng ta đã chỉ định trước đó.
Một lần nữa, cấu hình này dành riêng cho Keycloak và có thể khác đối với các triển khai Máy chủ OAuth khác.
Tham khảo
Trong bài viết này, chúng ta tập trung vào việc thiết lập dự án Spring Security OAuth2 của chúng ta để sử dụng JSON Token web.
Bạn có thể tìm thấy toàn bộ hướng dẫn này trên GitHub.
Cảm ơn các bạn đã dành thời gian cho bài viết này.
Last updated