thắc mắc Authorization trong microservice như nào cho hợp lý

losser50cm

Member
Em chào các bác, em đang mày mò làm một project microservice (Spring boot + Spring cloud) mà bị mắc đoạn authz cho các enpoints trong service con.

Cụ thể là có một Gateway để hứng request từ client. Khi nhận được JWT nó sẽ call về Auth-service để validate cái token đấy.

Vấn đề là khi request được gateway cho đi qua, nó chui vào trong service con nhưng em lại không biết request đấy tới từ ai bởi vì các service con hiện tại không dinh níu gì tới security cả (nên coi như token lúc bị vô dụng). Em đang nghĩ tới phương án đấy là config security cho từng service rồi lại cho gateway gửi kèm token về với mỗi request. Lúc này các service con sẽ tự decode token ra và validate lần nữa (nghe có vẻ hơi đần:beat_brick:). Mong các bác cho em phương án phù hợp với. Em đang làm theo luồng kiểu như bên dưới
microservice-security.jpg
 
Cách 1: set role trong token. API gateway parse role từ token và sử dụng Spring security để phân quyền.
Cách 2: api gateway relay user_id từ token xuống service. Service get user từ user-service/db/cache để thực hiện phân quyền. Cách này thường áp dụng cho các case phức tạp.
 
Cách 1: set role trong token. API gateway parse role từ token và sử dụng Spring security để phân quyền.
Cách 2: api gateway relay user_id từ token xuống service. Service get user từ user-service/db/cache để thực hiện phân quyền. Cách này thường áp dụng cho các case phức tạp.
Theo như cách 1 tức là mình sẽ dồn tất cả các enpoints vào trong config như này ở Gateway đúng không bác

Java:
@Bean
protected SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http...

        http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    return http.build();
}
 
cái này không có cách tốt nhất đâu, phụ thuộc vào đặc điểm của từng hệ thống mà làm, ví dụ như hệ thống kia của thím, có thể làm cách là sau khi xác thực ở con auth service trả về response cho gateway, gateway gắn payload vào header để forward request đến các service con, vấn đề của cách này là các service kia phải trust gateway 100%, và các service đó hoạt động internal, chứ nếu external thì coi như cách này bỏ, tiếp cách khác là từng con service kia gọi vào con auth kia để xác thực lần lượt, lúc này thì tải cho con auth kia sẽ tăng lên, nên bài toán lúc này là xử lý con auth, một cách khác hoàn toàn nữa là xác thực kiểu như bên oauth2, từng con service xác thực qua con auth service, sau đó sẽ tự kiểm soát xác thực của từng service, anw, nhiều cách lắm, tự cân đối với bài toán thôi
 
nếu thím có 1 con api gateway như con Ambassador hoặc Ingress Nginx, thì có thể sử dụng thêm con Ory Oathkeeper, con này nó support gọi ra 1 endpoint validate token của mình và thêm các header về thông tin người dùng (tùy mình thích thêm j thì thêm) vào request đến, các service bên trong chỉ bóc header ra thôi, rất nhàn
Edit: ory nó có cả full stack về authen và author luôn, thím có thể tham khảo
 
cái này không có cách tốt nhất đâu, phụ thuộc vào đặc điểm của từng hệ thống mà làm, ví dụ như hệ thống kia của thím, có thể làm cách là sau khi xác thực ở con auth service trả về response cho gateway, gateway gắn payload vào header để forward request đến các service con, vấn đề của cách này là các service kia phải trust gateway 100%, và các service đó hoạt động internal, chứ nếu external thì coi như cách này bỏ, tiếp cách khác là từng con service kia gọi vào con auth kia để xác thực lần lượt, lúc này thì tải cho con auth kia sẽ tăng lên, nên bài toán lúc này là xử lý con auth, một cách khác hoàn toàn nữa là xác thực kiểu như bên oauth2, từng con service xác thực qua con auth service, sau đó sẽ tự kiểm soát xác thực của từng service, anw, nhiều cách lắm, tự cân đối với bài toán thôi
Bác cho em hỏi là nếu làm theo như cách 1 thì có phương án nào để chặn bên ngoài không thể request bằng port của những service con không nhỉ

Còn nếu làm theo cách 2 thì sẽ là client -> gateway -> microservice -> call lên auth service để check rồi nhận lại kết quả. Lúc này có thể if else hay như nào đó để quyết định đi tiếp vào resource bên trong của service đó hay không đúng không bác. Nếu như này em thấy có vẻ hơi thủ công
 
nếu thím có 1 con api gateway như con Ambassador hoặc Ingress Nginx, thì có thể sử dụng thêm con Ory Oathkeeper, con này nó support gọi ra 1 endpoint validate token của mình và thêm các header về thông tin người dùng (tùy mình thích thêm j thì thêm) vào request đến, các service bên trong chỉ bóc header ra thôi, rất nhàn
Edit: ory nó có cả full stack về authen và author luôn, thím có thể tham khảo
Nếu làm như vậy tức là mình sẽ gộp luôn authen và author vào gateway luôn đún gkhoong bác
 
Bác cho em hỏi là nếu làm theo như cách 1 thì có phương án nào để chặn bên ngoài không thể request bằng port của những service con không nhỉ

Còn nếu làm theo cách 2 thì sẽ là client -> gateway -> microservice -> call lên auth service để check rồi nhận lại kết quả. Lúc này có thể if else hay như nào đó để quyết định đi tiếp vào resource bên trong của service đó hay không đúng không bác. Nếu như này em thấy có vẻ hơi thủ công
ý là ở đây service đó phải chạy internal, nếu bên ngoài cần dùng nó thì gần như là bỏ, còn chặn thì config network là được thôi, còn cách 2 thì bản chất chỉ cần middleware trước khi request vào controller của các service đó thôi, middleware này gọi lên auth để xác thực, làm như bình thường thôi, chỉ là bình thường phải decode token, chọc vào db lấy thông tin, thì giờ call lên auth service
 
ý là ở đây service đó phải chạy internal, nếu bên ngoài cần dùng nó thì gần như là bỏ, còn chặn thì config network là được thôi, còn cách 2 thì bản chất chỉ cần middleware trước khi request vào controller của các service đó thôi, middleware này gọi lên auth để xác thực, làm như bình thường thôi, chỉ là bình thường phải decode token, chọc vào db lấy thông tin, thì giờ call lên auth service
À có vẻ cách 2 em thấy ổn hơn ấy. Cảm ơn bác nhiều, để em thử :D
 
Thím tham khảo Role-based Access Control.
Cơ bản là khi user request một resource nào đấy thì nó phải được config trước và validate ngay ở gateway, sau khi request được được auth thì đi vào internal resource chỉ định rồi thì không có auth gì nữa.
 
Nếu làm như vậy tức là mình sẽ gộp luôn authen và author vào gateway luôn đún gkhoong bác
đúng r thím, authen hay author nó sẽ ở gateway hết, các request đi qua đc gateway đều sẽ có full thông tin đc authorized rồi, nên ko cần lo nghiệp vụ này nữa
 
chủ thớt hỏi về auth(Authentication), hay authz (Authorization) vậy?
qua được gateway auth rồi thì nếu mạng nội bộ coi như là xác thực rồi.
Sao thớt nói như kiểu đi qua gateway token mất luôn vậy? forward token sang cho các micro service mà authz chứ (hoặc phân quyền đơn giản thì gateway làm luôn)

Ở microservice Jwt decode không cần secret, chỉ verify mới cần secret
 
Em chào các bác, em đang mày mò làm một project microservice (Spring boot + Spring cloud) mà bị mắc đoạn authz cho các enpoints trong service con.

Cụ thể là có một Gateway để hứng request từ client. Khi nhận được JWT nó sẽ call về Auth-service để validate cái token đấy.

Vấn đề là khi request được gateway cho đi qua, nó chui vào trong service con nhưng em lại không biết request đấy tới từ ai bởi vì các service con hiện tại không dinh níu gì tới security cả (nên coi như token lúc bị vô dụng). Em đang nghĩ tới phương án đấy là config security cho từng service rồi lại cho gateway gửi kèm token về với mỗi request. Lúc này các service con sẽ tự decode token ra và validate lần nữa (nghe có vẻ hơi đần:beat_brick:). Mong các bác cho em phương án phù hợp với. Em đang làm theo luồng kiểu như bên dưới
View attachment 2003802
vậy bỏ con gateway đi là đúng architect rồi đấy. call service nào service đấy tự đi autho
 
chủ thớt hỏi về auth(Authentication), hay authz (Authorization) vậy?
qua được gateway auth rồi thì nếu mạng nội bộ coi như là xác thực rồi.
Sao thớt nói như kiểu đi qua gateway token mất luôn vậy? forward token sang cho các micro service mà authz chứ (hoặc phân quyền đơn giản thì gateway làm luôn)

Ở microservice Jwt decode không cần secret, chỉ verify mới cần secret
Ý em là authorz á bác, tất nhiên đi qua gateway vẫn có thể dùng token đấy để authorization nhưng em muốn tìm cách để có thể authen lẫn authorz trong gateway luôn để những service bên trong không liên quan gì đến security nữa ấy. Nhưng mà em đang làm tạm theo như bác midnight_sun
nói là gateway chỉ có đúng 1 vai trò là chia port, còn tự các service sẽ call lên auth-service để xác thực

 
Về auth* trong microservice có nhiều hướng tiếp cận
Trước tiên đơn giản hóa bài toán bằng việc nói rằng bạn có 1 nguồn Identity / 1 Authority duy nhất

1/ Hướng tiếp cận sử dụng middleware / gateway. Auth* chỉ xảy ra tại middleware này. Tất cả các service khác không yêu cầu auth* . Client chỉ có thể tiếp cận khối microservice thông qua middleware / gateway để đảm bảo security. Middleware / Gateway này phải là một component đủ thông minh / chứa business logic để có thể gọi đến các service khác với access scope của token mà nó nhận được, đồng thời agggregate kết quả từ các service đằng sau nó

2/ Auth* ở mọi service. Ở đây mỗi service đều tự validate token. Trường hợp này thường gặp hơn ở dạng microservice mà mỗi service đều có thể phải expose trực tiếp interface của nó ra với thế giới. Với trường hợp này lại có một số cách xử lý khác nhau như
  • User token passthrough - Đẩy user token qua lại giữa các service
  • M2M - Sử dụng token riêng của service này để gọi đến service kia

Mỗi loại đều có điểm mạnh điểm yếu cả.

Để nói riêng về "API Gateway" thì đây là một khái niệm rất "mờ" - không có ai thật sự định nghĩa chính xác nó là cái gì, làm cái gì và làm như thế nào cả. Tốt nhất hãy nói là bạn đang sử dụng khái niệm API Gateway bằng công cụ nào, phục vụ cho những công việc gì thì sẽ dễ giao tiếp hơn
 
Back
Top