SOA / Layanan Mikro: Bagaimana menangani otorisasi dalam komunikasi antar-layanan?

18

Latar depan

Kami bergerak dari platform monolitik ke Arsitektur yang Berorientasi Layanan. Kami menerapkan prinsip-prinsip DDD yang sangat mendasar dan memisahkan domain kami di berbagai konteks yang berbeda. Setiap domain didistribusikan dan memaparkan layanan melalui API web (REST).

Karena sifat bisnis kami, kami memiliki layanan seperti Pemesanan , Layanan , Pelanggan , Produk , dll.

Kami juga telah menyiapkan Server Identitas (berdasarkan Thinktecture Identity Server 3) yang peran utamanya adalah:

  • Otentikasi terpusat (diberikan kredensial yang menerbitkan token)
  • Tambahkan klaim dalam token seperti: cakupan klien (sesuai klien maksud saya aplikasi yang melakukan permintaan), pengidentifikasi pelanggan (sesuai pelanggan saya maksud orang yang menggunakan aplikasi)

Kami juga memperkenalkan peran Gateway API yang memusatkan akses eksternal ke layanan kami. API Gateway menyediakan fungsionalitas yang tidak memerlukan pengetahuan mendalam tentang domain internal seperti:

  • Reverse proxy: merutekan permintaan yang masuk ke layanan internal yang sesuai
  • Versi: versi API Gateway memetakan ke berbagai versi layanan internal
  • Otentikasi: permintaan klien termasuk token yang dikeluarkan oleh Identity Server dan API Gateway memvalidasi token (pastikan pengguna tahu siapa dia)
  • Pembatasan: membatasi jumlah permintaan per klien

Otorisasi

Yang menyangkut otorisasi, ini tidak dikelola di API Gateway tetapi di layanan internal itu sendiri. Kami sedang melakukan 2 jenis otorisasi utama:

  • Otorisasi berdasarkan lingkup klien. Contoh: klien (aplikasi eksternal yang menggunakan API kami) memerlukan lingkup "pemesanan" untuk mengakses titik akhir API layanan Pemesanan
  • Otorisasi berdasarkan pelanggan. Contoh: hanya jika seorang pelanggan (orang fisik menggunakan aplikasi) adalah peserta pemesanan dapat mengakses titik akhir GET / pemesanan dari layanan Pemesanan

Untuk dapat menangani otorisasi dalam layanan internal, API Gateway hanya meneruskan token (saat merutekan permintaan ke layanan internal) yang mencakup informasi tentang klien (aplikasi yang melakukan permintaan) dan pelanggan sebagai klaim (dalam kasus-kasus di mana seseorang masuk dalam aplikasi klien).

Deskripsi masalah

Sejauh ini bagus sampai kami memperkenalkan komunikasi antar-layanan (beberapa layanan dapat berkomunikasi dengan layanan lain untuk mendapatkan beberapa data).

Pertanyaan

Bagaimana seharusnya kita mendekati otorisasi dalam komunikasi antar-layanan?

Opsi dipertimbangkan

Untuk membahas berbagai opsi saya akan menggunakan skenario sampel berikut:

  • Kami memiliki aplikasi eksternal bernama ExternalApp yang mengakses API kami ( ExternalApp dapat dilihat sebagai klien ) untuk membangun alur pemesanan
  • ExternalApp membutuhkan akses ke layanan Pemesanan , maka kami memberikan ExternalApp ruang lingkup "pemesanan"
  • Secara internal (ini adalah sesuatu yang sepenuhnya transparan untuk ExternalApp ) layanan Pemesanan mengakses layanan Layanan untuk mendapatkan layanan default dari pemesanan seperti penerbangan, asuransi atau penyewaan mobil

Saat membahas masalah ini secara internal, beberapa opsi muncul, tetapi kami tidak yakin opsi mana yang terbaik:

  1. Ketika Pemesanan berkomunikasi dengan Layanan , itu seharusnya hanya meneruskan token asli yang ia terima dari API Gateway (menunjukkan bahwa klien adalah ExternalApp )
    • Implikasi: Kita mungkin perlu memberikan ruang lingkup kepada ExternalApp yang seharusnya tidak diberikan. Contoh: ExternalApp mungkin perlu memiliki "pemesanan" dan "layanan" lingkup sementara hanya ruang lingkup "pemesanan" saja yang cukup.
  2. Ketika Pemesanan berkomunikasi dengan Layanan , itu meneruskan token yang menunjukkan klien sekarang telah menjadi Pemesanan (bukan ExternalApp ) + itu menambahkan klaim yang menunjukkan Pemesanan meniru identitas klien asli ExternalApp
    • Dengan juga memasukkan informasi bahwa klien asli adalah ExternalApp , Layanan Services juga dapat melakukan logika seperti menyaring beberapa layanan tergantung pada pemanggil asli (misalnya untuk aplikasi internal kita harus mengembalikan semua perkelahian, untuk aplikasi eksternal hanya beberapa)
  3. Layanan tidak boleh berkomunikasi satu sama lain (jadi kita bahkan tidak harus menghadapi pertanyaan ini)

Terima kasih sebelumnya atas masukan Anda.

Josep Serra
sumber
1
Bagaimana Anda mengatasi masalah ini? Kami berada dalam situasi yang sama.
Varun Mehta
+1: Saya tertarik pada bagaimana Anda akhirnya memecahkan masalah Anda.
Dypso
Untuk melakukan poin 3 - layanan tidak berkomunikasi satu sama lain, Anda memerlukan UI komposit. Lihat particular.net/blog/secret-of-better-ui-composition
stevie_c

Jawaban:

3

Saya menyarankan Anda untuk memiliki saluran komunikasi internal antara layanan microser.

Misalnya untuk menggunakan beberapa perantara pesan seperti RabbitMQ secara internal untuk mengirim / menerima atau menerbitkan / berlangganan pesan di antara layanan microser.

Maka pengguna akhir pertama Anda yang menghadapi layanan "dalam contoh Anda layanan Pemesanan" akan bertanggung jawab untuk memvalidasi token dan memberikan otorisasi kepada pelanggan untuk melakukan operasi spesifik ini mungkin dengan berkomunikasi dengan IdentityServer.

Kemudian akan berkomunikasi dengan layanan Layanan melalui broker pesan dan dalam hal ini, tidak perlu memvalidasi token lagi.

Saya kira model ini akan lebih sederhana dan memberi Anda kinerja yang lebih baik.

Wahid Bitar
sumber