Praktik standar untuk kontrol akses (pola desain)

9

Saya melihat desain antarmuka saya dan saya berjuang untuk memutuskan mana yang paling "benar" cara untuk menerapkan kontrol akses berbasis peran, mengingat userdan subjectyang useringin diakses.


Sejauh yang saya bisa lihat, saya memiliki tiga opsi inti (dengan yang keempat menjadi bastardisasi dari tiga yang pertama dan yang kelima menjadi tweak dari yang keempat):

  1. Minta subjectdengan daftar izin yang userdimiliki -subject.allowAccess(user.getPermissionSet)
  2. Permintaan userdengan daftar izin yang subjectdibutuhkan -user.hasPermissionTo(subject.getRequiredPermissions())
  3. Minta pihak ketiga untuk menemukan persimpangan izin - accessController.doPermissionSetsIntersect(subject.permissionSet, user.getPermissionSet())
  4. Minta salah satu dari subject/ user, sambil mendelegasikan "keputusan" ke kelas pihak ketiga
  5. Usahakan useruntuk mengakses subjectdan melemparkan kesalahan jika akses tidak diizinkan

Saya condong ke arah pilihan empat - Memiliki subjectmengandung accessControllerlapangan, di mana panggilan untuk subject.userMayAccess(User user)mendelegasikan operasi a la:

class Subject {
    public function display(user) {
        if(!accessController.doPermissionSetsIntersect(this.permissionSet, user.getPermissionSet())) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

.. tapi kemudian ini menimbulkan pertanyaan lebih lanjut:

  • haruskah accessControllerbidang vs kelas statis ..?
  • Haruskah subject mengetahui izin apa yang diperlukan untuk dapat melihatnya?
  • di mana asas paling sedikit ilmu berperan di sini, sehubungan dengan pemanggilan subject.display()? Haruskah penelepon subject.display()mengetahui bahwa kontrol akses berlaku? (di mana subject.display()"metode templat" terakhir)
  • telah subject.display()mengelola kontrol akses, melemparkan pengecualian di mana pengguna tidak memiliki izin yang diperlukan?

Apa yang akan dianggap "praktik terbaik" dalam situasi ini? Di mana seharusnya tanggung jawab untuk melakukan pemeriksaan sebenarnya terjadi?

Karena ini merupakan latihan akademis yang kemudian akan berkembang menjadi implementasi, referensi untuk pola desain akan dihargai.

kwah
sumber

Jawaban:

7

Praktik terbaik adalah menggunakan sesuatu yang dikenal sebagai pola Pencegat untuk mencegat panggilan ke kawasan lindung.

Ini dapat dicapai dengan menggunakan AOP atau masalah lintas sektoral yang diterapkan pada titik masuk akses Anda.

Subjek tidak boleh tahu tentang siapa yang bisa melihatnya. Ini mempersulit kode subjek yang tidak perlu dan tidak ada alasan untuk mengharuskannya, kecuali Anda secara tidak sengaja menyediakan mekanisme akses langsung ke fungsi yang sama.

Lebih disukai penelepon dan callee tidak tahu tentang akses, selain menangani penolakan. Namun, masalah ini akan tergantung pada sistem yang Anda laksanakan dan bagaimana Anda mendapatkan akses ke kredensial / pelaku keamanan untuk penelepon. Sebagai contoh, dalam sistem SOAP informasi ini ditambahkan ke header pesan SOAP, sedangkan dalam sistem windows itu akan tersedia melalui mekanisme otentikasi windows.

Jika Anda menggunakan pendekatan AOP atau pola pencegat itu akan membuang pengecualian yang diperlukan, dan itu akan menjadi tanggung jawab klien (penelepon) untuk menangani pengecualian yang dilemparkan.

Dengan cara ini Anda menjaga kode klien, layanan, dan otentikasi Anda terpisah tanpa ada percampuran pengetahuan atau fungsionalitas.

sweetfa
sumber
2

Saya pikir pilihan Anda 3 adalah yang paling dekat, tetapi alih-alih menginterogasi userdan subjecttentang set izin mereka, Anda harus meneruskan userdan subjectke pengontrol akses.

class Subject {
    public function display(user) {
        if(!accessController.checkAccess(this, user, AccessControl.Read)) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

Pengontrol akses harus bertanggung jawab untuk mendapatkan set izin dan memeriksa apakah aksesnya memadai. Dengan begitu Anda mengisolasi logika penyimpanan dan logika pemeriksaan di pengontrol akses Anda, terpisah dari pengguna dan subjek.

Elemen lain yang mungkin hilang dari contoh Anda adalah operasi apa yang sedang dilakukan. Beberapa pengguna mungkin memiliki hak untuk membaca beberapa data tetapi tidak untuk memperbarui, menghapus, mengeksekusi, dll Jadi Anda mungkin memiliki checkAccessmetode pada kontroler akses dengan tiga parameter: user, subject, operation. Anda mungkin juga ingin memberikan beberapa informasi tambahan checkAccessuntuk mengembalikan informasi tentang mengapa akses tidak diberikan.

Misalnya, mendelegasikan semua ini ke pengontrol akses nanti memungkinkan Anda untuk mengganti cara izin Anda diwakili. Anda mungkin mulai dengan kontrol akses berbasis peran dan pindah ke berbasis klaim nanti. Anda dapat menyimpan izin dalam struktur sederhana untuk memulai dan kemudian menambahkan grup hierarki / peran dan operasi yang diizinkan pada berbagai jenis subjek. Tidak menempatkan set izin Anda ke antarmuka membantu mengaktifkannya.

Apakah Anda menggunakan AOP atau kode boilerplate untuk menyambungkan ini, menurut pendapat saya, kurang penting.

Rory
sumber