2013-04-23 11 views
8

Tôi có một trang web sử dụng bảo mật Spring và có người dùng (tên người dùng & mật khẩu) và xác thực biểu mẫu chuẩn. Tôi cho phép người dùng tạo Id ứng dụng khách và bí mật ứng dụng khách được liên kết với tài khoản của họ để sử dụng với API phần còn lại được bảo đảm OAuth2.Bảo mật mùa xuân oauth2 - nhận dữ liệu tùy chỉnh từ mã OAuth2 chính

tôi sử dụng một id khách hàng bí mật & khách hàng riêng biệt cho các API và không username và mật khẩu vì vậy người dùng có thể thay đổi mật khẩu của họ vv mà không vi phạm các chứng chỉ API, thiết lập phạm vi cụ thể, vô hiệu hóa truy cập API, vv

tôi sử dụng spring-security-oauth2 (nhà cung cấp) để bảo mật API còn lại và tôi đã cho phép luồng thông tin khách hàng. Tôi đã thiết lập xác thực máy khách cho api để id khách hàng và bí mật được kiểm tra.

Từ một ứng dụng riêng biệt, tôi sử dụng id ứng dụng khách và bí mật của khách hàng để truy xuất mã thông báo truy cập và bắt đầu sử dụng nó với api. Đối với hầu hết các phần, tôi sử dụng các biểu thức @PreAuthorize đơn giản thường dựa trên vai trò và phạm vi ứng dụng khách và chúng xuất hiện để hoạt động chính xác.

Tất cả ở trên xuất hiện để làm việc tốt

Tuy nhiên ... Tôi có một vài điểm cuối API Tuy nhiên bây giờ mà tôi cần phải thực hiện một số quy định phức tạp hơn dựa trên một số chi tiết từ người dùng cơ bản - trong trường hợp này người dùng đã tạo id khách hàng và bí mật.

Ví dụ đơn giản xem xét ứng dụng nhắn tin nơi tôi có điểm cuối cho phép người dùng đăng "thông điệp" mới của một loại cụ thể có thể thay đổi. Tôi có một bảng người nhận được phép cho mỗi người dùng và mỗi loại và tôi muốn kiểm tra xem người nhận tin nhắn đã đăng có khớp với người nhận được phép đối với loại đó không. (Dữ liệu người nhận được cho phép thường không lớn và hiếm khi thay đổi, vì vậy tôi rất vui khi lưu trữ bản sao của nó khi tạo mã thông báo truy cập)

Tôi nhận được hiệu trưởng tại các điểm cuối này và tôi thấy nó là một trường hợp của OAuth2Authentication có chứa:

  • userAuthentication - null - Điều này có vẻ mong đợi đối với luồng thông tin khách hàng.
  • clientAuthentication là dân cư và authorizationParameters chứa các loại trợ cấp và client_id

Tôi cho rằng tôi có thể sử dụng id khách hàng từ clientAuthentication.authorizationParameters để tra cứu người sử dụng và các chi tiết tôi cần, nhưng đó sẽ là một vài truy vấn mỗi api gọi mà dường như không có ý nghĩa. Tôi có thể có một địa điểm/cách tốt trong thư viện Spring OAuth2 trong khi cấp mã thông báo truy cập để tôi có thể thêm một số chi tiết bổ sung để sau này tôi có thể lấy chúng từ đối tượng OAuth2Authentication (chính) (hoặc cái gì đó mở rộng nó). ?)

Ngoài ra, có cách tiếp cận tốt hơn hoàn toàn cho vấn đề đó không?

Thx!

+0

Bạn đã nhìn JWT (JSON web token)? Đó là khá nhiều mã thông báo có tất cả thông tin hữu ích trong đó. – kaqqao

Trả lời

5

Bạn có thể ghi đè lớp tạo mã thông báo để mã thông báo có chứa tên người dùng. (có thể được mã hóa bằng client_secret). Bằng cách này, bạn có thể khiến người dùng liên quan đến mã thông báo từ chính mã thông báo mà không cần truy cập cơ sở dữ liệu bổ sung. bạn nên ghi đè

với lớp của riêng bạn, hoặc sử dụng TokenEnhancer

+0

Thx, ban đầu có vẻ đầy hứa hẹn. Tôi sẽ kiểm tra nó nhiều hơn và thực hiện một số xét nghiệm vào ngày hôm sau. Tôi đã không tìm thấy một bài báo/bài/mẫu nào được nêu ra nếu bạn biết về một cái hãy cho tôi biết :) –

+0

Xin chào, tôi đã kiểm tra và có vẻ như TokenEnhancer hữu ích để "nâng cao" phản hồi mã thông báo truy cập và/hoặc thêm một số thông tin bổ sung. Mặc dù đó không phải là điều tôi muốn. Không cần gửi thêm dữ liệu cho khách hàng. Trong khi tôi hiểu ý tưởng của bạn để cố gắng để nhồi nhét tên người dùng vào mã thông báo (tôi thường không cần nó) có vẻ như với tôi rằng phải có một cách tốt hơn để giữ các thẻ không thay đổi và chỉ xảy ra ở phía máy chủ. –

+0

bạn có thể thêm thông tin bạn cần vào Chi tiết Khách hàng khi bạn đăng ký từng khách hàng bằng cách sử dụng 'ClientDetails.addAdditionalInformation' Hơn bạn có thể lấy lại thông tin này bằng cách sử dụng' clientId' mà bạn có. (điều này có thể yêu cầu một truy vấn cho mỗi yêu cầu có vẻ hợp lý) – achiash

6

Tại sao bạn không sử dụng Phạm vi có thể được xác định trong chi tiết khách hàng và sau đó sử dụng ScopeVoter để xác thực là mã thông báo này có phạm vi thích hợp để truy cập tài nguyên này hay không.

hãy kiểm tra bản demo của tôi để biết thêm chi tiết

https://github.com/bassemZohdy/Spring_REST_OAuth_Demo

Cập nhật 1: Tôi không trả lời phần 2 của câu hỏi của bạn "nhận được dữ liệu tùy chỉnh từ OAuth2 chính" bạn có thể thêm dịch vụ còn lại trên Authorization của bạn máy chủ được truy cập bằng mã thông báo OAuth để cung cấp cho bạn thông tin bắt buộc về người dùng mã thông báo này, vì vậy bạn không phải quan tâm đến "OAuth2 principal" bạn đang xử lý máy chủ Ủy quyền làm máy chủ tài nguyên.

+0

Thx, tôi đang sử dụng một số phạm vi đơn giản nhưng đã tránh được giải pháp như tôi đã lo lắng về một số lượng bùng nổ của phạm vi để đạt được các quy tắc tôi muốn. Tôi sẽ cập nhật câu hỏi với một ví dụ. –

+0

Trong một giải pháp khác tôi đang sử dụng phạm vi cho mỗi nhóm tài nguyên, tôi nghĩ rằng không có giới hạn về nuber của phạm vi, bạn cũng có thể kết hợp phạm vi với vai trò. –

+0

Thx, vâng tôi đã sử dụng một chút rồi. Chỉ cần cho trường hợp tôi đề cập đến nó sẽ có khả năng khá tâm uốn để xây dựng các phạm vi từ người sử dụng và sau đó xử lý chúng để giải thích chúng :-) Tôi hy vọng có một cách tốt hơn. –

5

Theo ý kiến ​​của tôi, cách tiếp cận đúng ở đây là sử dụng luồng mật khẩu "oauth2" thay vì thông tin đăng nhập của khách hàng. bạn có thể tạo một client-id chung và client-secret và cung cấp cho tất cả người dùng của bạn. mỗi người dùng có thể yêu cầu mã thông báo của riêng mình bằng cách sử dụng các chi tiết khách hàng đó và tên người dùng và mật khẩu của riêng họ. Bằng cách này, mỗi mã thông báo sẽ được kết nối với một đối tượng UserDetails sẽ giải quyết vấn đề của bạn. Bạn có thể xem cách thực hiện việc này tại đây: https://labs.hybris.com/2012/06/18/trying-out-oauth2-via-curl/

+1

Thx để biết ý tưởng, nhưng điểm sử dụng bằng chứng xác thực của khách hàng là làm cho API nói chung độc lập với người dùng. Chỉ trong một vài trường hợp (thiểu số) tôi mới có một số quy tắc phức tạp hơn. Tôi đã cập nhật câu hỏi để đưa ra lý do cho thông tin đăng nhập của khách hàng. –

+0

Liên kết ở đây bị hỏng. Bạn có thể mang lại một đoạn trích có liên quan của câu trả lời cụ thể này không? – Makoto

+0

Đã sửa lỗi liên kết. – achiash