Periksa apakah pengguna memiliki akses ke halaman tertentu

23

Bagaimana saya bisa menentukan apakah pengguna memiliki izin untuk mengakses halaman tertentu?

farzan
sumber
Anda tidak menentukan versi Drupal yang Anda gunakan. Rincian lebih lanjut tentang tujuan Anda juga akan berguna; dalam kasus yang paling umum, Drupal akan menangani akses menu secara otomatis.
Dylan Tack

Jawaban:

25

Jika Anda ingin memverifikasi apakah pengguna yang saat ini masuk memiliki akses ke halaman, Anda dapat menggunakan kode berikut:

if ($router_item = menu_get_item($path)) {
  if ($router_item['access']) {
    // The user has access to the page in $path.
  }
}

$path adalah jalur halaman yang ingin Anda periksa (mis. simpul / 1, admin / pengguna / pengguna).

Kode ini berfungsi di Drupal 6 dan versi yang lebih tinggi, dan itu adalah kode yang digunakan dari menu_execute_active_handler () .

Alasan saya tidak menyarankan untuk langsung memanggil akses callback adalah karena argumen yang perlu diteruskan ke fungsi itu.

Kode yang digunakan oleh _menu_check_access () adalah yang berikut (Drupal 7):

$arguments = menu_unserialize($item['access_arguments'], $map);
// As call_user_func_array is quite slow and user_access is a very common
// callback, it is worth making a special case for it.
if ($callback == 'user_access') {
  $item['access'] = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
}
elseif (function_exists($callback)) {
  $item['access'] = call_user_func_array($callback, $arguments);
}

Kode, yang perlu sebanyak mungkin generik, tidak secara langsung menangani objek pengguna. Ini berarti bahwa tidak mungkin untuk mengganti objek pengguna untuk pengguna yang saat ini masuk dengan objek pengguna lain.
Kode harus cukup umum untuk menangani definisi menu seperti yang berikut:

$items['node/add/' . $type_url_str] = array(
  'title' => $type->name, 
  'title callback' => 'check_plain', 
  'page callback' => 'node_add', 
  'page arguments' => array($type->type), 
  'access callback' => 'node_access', 
  'access arguments' => array('create', $type->type), 
  'description' => $type->description, 
  'file' => 'node.pages.inc',
);

$items['node/%node'] = array(
  'title callback' => 'node_page_title', 
  'title arguments' => array(1),
  // The page callback also invokes drupal_set_title() in case
  // the menu router's title is overridden by a menu link. 
  'page callback' => 'node_page_view', 
  'page arguments' => array(1), 
  'access callback' => 'node_access', 
  'access arguments' => array('view', 1),
);

Di kedua definisi, argumen akses tidak menyertakan objek pengguna, dan node_access () dalam hal ini menggunakan objek pengguna untuk pengguna yang saat ini masuk. Dalam kasus kedua, salah satu argumennya adalah objek simpul yang diperoleh dari URL; misalnya, jika URL adalah example.com/node/1, maka argumen kedua yang diteruskan ke akses panggilan balik adalah objek simpul untuk simpul dengan simpul ID sama dengan 1.
Menulis kode yang menangani kasus-kasus ini juga berarti menduplikasi kode sudah ada di Drupal. Bahkan jika Anda menggandakan kode itu, masih akan ada masalah panggilan balik akses yang memeriksa akses terhadap pengguna yang saat ini masuk.

Jika Anda ingin memeriksa apakah pengguna yang bukan pengguna login saat ini dapat mengakses menu adalah untuk pertama-tama mengubah nilai variabel global $user, gunakan kode yang saya laporkan di awal jawaban saya, dan kemudian kembalikan nilai dari $user. Untuk cara mengubah nilai global $user, Anda dapat melihat secara program menyamar sebagai pengguna lain tanpa menyebabkan pengguna yang saat ini masuk untuk keluar . Perbedaannya adalah, alih-alih menggunakan nilai yang dikembalikan dari drupal_anonymous_user () , Anda menggunakan nilai yang dikembalikan dari user_load () .

kiamlaluno
sumber
Boleh saya tahu di mana kait kode ini harus ditulis.
Gladiator
14

Coba drupal_valid_path () .

Fungsi mengembalikan TRUEadalah jalur yang dilewati sebagai argumen ada dan pengguna saat ini memiliki akses ke sana. Jadi, jika Anda bekerja pada Drupal 7 dan Anda perlu memeriksa akses pada pengguna yang saat ini masuk, itu adalah cara termudah untuk pergi:

if (drupal_valid_path('my/path')) {
  // Your code here...
}
peterpoe
sumber
1
Di D7, drupal_valid_pathmelakukan pekerjaan dengan sempurna dan dibuat untuk memenuhi kebutuhan yang tepat ini. Ini menggunakan menu_get_item dan memeriksa akses juga.
Weboide
Itu benar, tetapi itu hanya berfungsi untuk pengguna yang saat ini masuk. Jika Anda ingin tahu apakah beberapa pengguna lain dapat mengakses jalur, drupal_valid_pathtidak akan membantu Anda.
Andrew Schulman
@AndrewSchulman Saya tidak berpikir ada API untuk itu, tetapi Anda dapat beralih sementara pengguna.
peterpoe
Di Drupal 8, ini telah pindah ke \Drupal::service('path.validator')->isValid($path);- lihat dokumentasi API
Gogowitsch
3

Panggil access callbackyang ditentukan dalam entri menu yang bertanggung jawab untuk halaman tersebut. Entri menu itu biasanya dibuat oleh Drupal yang memanggil implementasi hook_menudan disimpan di suatu tempat dalam database. Berhati-hatilah bahwa data yang dikembalikan oleh hook_menudapat diubah oleh implementasi modul hook_menu_alter.

Berhati-hatilah bahwa beberapa modul mungkin tidak meneruskan pengguna sebagai argumen yang terpisah (seperti yang ditentukan oleh access argumentskunci entri menu), tetapi sebaliknya mungkin menggunakan $userobjek global sebagai gantinya. Anda harus memeriksa ini untuk setiap modul yang Anda gunakan.

Oswald
sumber
Metode ini dapat digunakan untuk mencari tahu apakah beberapa pengguna selain pengguna yang bertindak diizinkan untuk mengakses halaman.
Oswald
1
Memanggil panggilan balik akses tidak semudah memanggil fungsi lain, karena panggilan balik akses membutuhkan argumen tertentu; lihat _menu_check_access () , yang merupakan fungsi yang memeriksa apakah pengguna yang saat ini masuk memiliki akses ke menu.
kiamlaluno
2

Lihat user_access()fungsinya. Lihat tautan untuk parameter yang ditentukan untuk setiap versi Drupal. Dari halaman dokumentasi untuk Drupal 7-8:

Parameter

$ string Izin, seperti "kelola node", sedang diperiksa.

$ akun (opsional) Akun yang akan diperiksa, jika tidak digunakan, pengguna yang masuk saat ini.

Nilai pengembalian

Boolean TRUE jika pengguna saat ini memiliki izin yang diminta.

Semua pemeriksaan izin di Drupal harus melalui fungsi ini. Dengan cara ini, kami menjamin perilaku yang konsisten, dan memastikan bahwa pengguna super dapat melakukan semua tindakan.

Laxman13
sumber
user_access () adalah untuk memeriksa apakah pengguna memiliki "tipe" izin tertentu. Yang diperlukan adalah jika pengguna dapat mengakses "jalur" tertentu; misalnya, apakah pengguna dapat mengakses 'node / 12'?
farzan
Nah bagaimana Anda menentukan kapan pengguna memiliki izin atau tidak? Saya akan berasumsi ada opsi pada halaman izin yang telah Anda periksa atau tidak untuk memberikan peran tertentu izin
Laxman13
user_access()tidak selalu merupakan akses balik panggilan yang digunakan oleh suatu menu; bahkan jika itu terjadi, Anda harus tahu argumen akses yang perlu Anda sampaikan user_access().
kiamlaluno
Saya tahu itu tidak selalu user_access(), hanya mengira OP memiliki izin untuk memeriksa untuk melihat apakah pengguna harus memiliki akses. Bukan pertanyaan yang sangat deskriptif
Laxman13
Meskipun user_access tidak dapat memeriksa akses ke jalur tertentu, saya pikir menggunakan user_access bila memungkinkan adalah cara terbaik untuk memeriksa akses. Jawaban yang bagus @ Laxman13 +1.
AyeshK
2

Jika Anda perlu tahu apakah pengguna dapat mengakses node tertentu, dan menggunakan modul akses node, Anda dapat menggunakan node_access () . (tanpa modul akses simpul, mereka hanya memerlukan izin 'akses konten'.)

Jika Anda ingin mengetahui apakah pengguna dapat mengakses jalur arbitrer yang ditentukan oleh implementasi hook_menu (), Anda mungkin harus mengambil entri menu dari database dan mengevaluasi parameter 'akses panggilan balik'.

Gapple
sumber
2
    $node = node_load(123);

    $account = user_load(456);

    if (node_access("update", $node, $account) === TRUE) 
   {

         print "access";    
    }
Mahipal Purohit
sumber