Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Benutzerkontenverwaltung, Rollen, Berechtigungen, Authentifizierung PHP und MySQL – Teil 5

Dies ist Teil 5 einer Reihe zum Erstellen eines Verwaltungssystems für Benutzerkonten in PHP. Die anderen Teile findest du hier:Teil 1, Teil 2, Teil 3 und Teil 4.

Wir haben im letzten Abschnitt die Verwaltung von administrativen Benutzerkonten sowie Rollen abgeschlossen. In diesem Teil gehen wir durch das Erstellen von Berechtigungen und das Zuweisen und Aufheben der Zuweisung von Berechtigungen zu Benutzerrollen.

Zuweisen von Berechtigungen zu Rollen

Wie ich im ersten Teil dieser Serie sagte, beziehen sich Rollen auf Berechtigungen in einer Many-to-Many-Beziehung. Eine Rolle kann viele Berechtigungen haben und eine Berechtigung kann zu vielen Rollen gehören.

Wir haben bereits die Rollentabelle erstellt. Jetzt erstellen wir eine Berechtigungstabelle für Berechtigungen und eine dritte Tabelle namens permission_role für die Informationen über die Beziehung zwischen der Rollen- und Berechtigungstabelle.

Erstellen Sie die beiden Tabellen mit den folgenden Eigenschaften:

Berechtigungstabelle:

CREATE TABLE `permissions` (
 `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
 `name` varchar(255) NOT NULL UNIQUE KEY,
 `description` text NOT NULL
)

permission_role-Tabelle:

CREATE TABLE `permission_role` (
 `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
 `role_id` int(11) NOT NULL,
 `permission_id` int(11) NOT NULL,
 KEY `role_id` (`role_id`),
 KEY `permission_id` (`permission_id`),
 CONSTRAINT `permission_role_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `permission_role_ibfk_2` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`)
)

In der Tabelle permission_role verweist die role_id auf die Rollen-ID in der Tabelle roles, während die permission_id auf die Spalte Berechtigungs-ID in der Berechtigungstabelle verweist. Um einer Rolle eine Berechtigung zuzuweisen, fügen wir einfach einen Datensatz dieser permission_id gegen die role_id in der permission_role-Tabelle ein, und die Beziehung wird hergestellt. Das heißt, wenn wir die Zuweisung dieser Berechtigung von dieser Rolle aufheben möchten, löschen wir einfach den Datensatz dieser role_id für diese permission_id in dieser permission_role-Tabelle.

Die letzten beiden Zeilen der obigen SQL-Abfrage sind Einschränkungen, die sicherstellen, dass beim Löschen einer bestimmten Rolle oder Berechtigung alle Einträge in der Tabelle permission_role mit dieser Berechtigungs-ID oder dieser Rollen-ID ebenfalls automatisch von der Datenbank gelöscht werden. Wir tun dies, weil wir nicht wollen, dass die Tabelle permission_role Beziehungsinformationen über eine Rolle oder eine Berechtigung enthält, die nicht mehr existiert.

Sie können diese Einschränkungen auch manuell mit PHPMyAdmin festlegen:Sie können dies auf der Benutzeroberfläche tun, indem Sie einfach die Tabelle permission_role auswählen und zur Registerkarte Relationale Ansicht> Struktur gehen und einfach die Werte eingeben. Wenn Sie dies immer noch nicht tun können, hinterlassen Sie unten einen Kommentar und ich werde versuchen, Ihnen zu helfen.

Jetzt ist die Beziehung festgelegt.

Lassen Sie uns eine Seite erstellen, um einer Rolle Berechtigungen zuzuweisen. Auf unserer Seite roleList.php listen wir die verschiedenen Rollen mit einer Schaltfläche „Berechtigungen“ daneben auf. Wenn Sie auf diesen Link klicken, gelangen Sie zu einer Seite namens assignPermissions.php. Lassen Sie uns diese Datei jetzt im Ordner admin/roles erstellen.

AssignPermissions.php:

<?php include('../../config.php') ?>
<?php include(ROOT_PATH . '/admin/roles/roleLogic.php') ?>
<?php
  $permissions = getAllPermissions();
  if (isset($_GET['assign_permissions'])) {
    $role_id = $_GET['assign_permissions']; // The ID of the role whose permissions we are changing
    $role_permissions = getRoleAllPermissions($role_id); // Getting all permissions belonging to role

    // array of permissions id belonging to the role
    $r_permissions_id = array_column($role_permissions, "id");
  }
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Admin Area - Assign permissions </title>
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
  <!-- Custome styles -->
  <link rel="stylesheet" href="../../static/css/style.css">
</head>
<body>
  <?php include(INCLUDE_PATH . "/layouts/admin_navbar.php") ?>
  <div class="col-md-4 col-md-offset-4">
    <a href="roleList.php" class="btn btn-success">
      <span class="glyphicon glyphicon-chevron-left"></span>
      Roles
    </a>
    <hr>
    <h1 class="text-center">Assign permissions</h1>
    <br />
    <?php if (count($permissions) > 0): ?>
    <form action="assignPermissions.php" method="post">
      <table class="table table-bordered">
        <thead>
          <tr>
            <th>N</th>
            <th>Role name</th>
            <th class="text-center">Status</th>
          </tr>
        </thead>
        <tbody>
          <?php foreach ($permissions as $key => $value): ?>
            <tr class="text-center">
              <td><?php echo $key + 1; ?></td>
              <td><?php echo $value['name']; ?></td>
              <td>
                  <input type="hidden" name="role_id" value="<?php echo $role_id; ?>">
                  <!-- if current permission id is inside role's ids, then check it as already belonging to role -->
                  <?php if (in_array($value['id'], $r_permissions_id)): ?>
                    <input type="checkbox" name="permission[]" value="<?php echo $value['id'] ?>" checked>
                  <?php else: ?>
                    <input type="checkbox" name="permission[]" value="<?php echo $value['id'] ?>" >
                  <?php endif; ?>
              </td>
            </tr>
          <?php endforeach; ?>
          <tr>
            <td colspan="3">
              <button type="submit" name="save_permissions" class="btn btn-block btn-success">Save permissions</button>
            </td>
          </tr>
        </tbody>
      </table>
    </form>
    <?php else: ?>
      <h2 class="text-center">No permissions in database</h2>
    <?php endif; ?>
  </div>
  <?php include(INCLUDE_PATH . "/layouts/footer.php") ?>
</body>
</html>

Durch Klicken auf die Schaltfläche „Berechtigungen“ einer Rolle gelangen Sie zu dieser Seite. Aber jetzt, wenn Sie darauf klicken und zu dieser Seite assignPermissions.php kommen, gibt es eine Fehlermeldung, die besagt, dass getAllPermissions()-Funktionen nicht definiert sind. Bevor wir diese Methode hinzufügen, sehen wir uns an, wie wir diese Zuweisung und Aufhebung von Berechtigungen tatsächlich in unserem PHP-Code implementieren.

Wenn Sie auf die Schaltfläche „Berechtigungen“ einer Rolle klicken, werden Sie zur Seite „assignPermissions.php“ mit der ID dieser Rolle weitergeleitet. Bevor wir jedoch die Seite „Berechtigungen zuweisen“ anzeigen, verwenden wir die Rollen-ID, um alle Berechtigungen abzurufen, die dieser Rolle bereits aus der Datenbank zugewiesen wurden. Und dann bringen wir auch alle verfügbaren Berechtigungen in der Berechtigungstabelle heraus. Jetzt haben wir zwei Arrays von Berechtigungen:diejenigen, die einer Rolle zugewiesen wurden, und alle Berechtigungen, die in unserer Datenbank verfügbar sind. Eine erstere ist eine Teilmenge der letzteren.

Das Zuweisen einer Berechtigung zu einer Rolle bedeutet, dass diese Berechtigung aus der Gesamtliste der Berechtigungen zu dem Berechtigungs-Array hinzugefügt wird, das zu dieser Rolle gehört, und dass alle diese Informationen in der Tabelle permission_role gespeichert werden. Das Zuweisen einer Berechtigung zu einer Rolle aufzuheben bedeutet, diese bestimmte Berechtigung aus der Liste der Berechtigungen zu entfernen, die zu dieser Rolle gehören.

Unsere Logik besteht darin, ein Array aller verfügbaren Berechtigungen aus der Datenbank zu durchlaufen und dann für jede ihrer IDs festzustellen, ob diese ID bereits im Array von IDs für die Berechtigungen der Rolle enthalten ist. Wenn es existiert, bedeutet dies, dass die Rolle diese Berechtigung bereits hat, also zeigen wir sie neben einem aktivierten Kontrollkästchen an. Wenn es nicht vorhanden ist, zeigen wir es neben einem deaktivierten Kontrollkästchen an.

Nachdem alles angezeigt wurde, bedeutet das Klicken auf ein aktiviertes Kontrollkästchen, dass die Zuweisung der Berechtigung aufgehoben wird, während das Klicken auf ein deaktiviertes Kontrollkästchen bedeutet, dass die Berechtigung der Rolle zugewiesen wird. Nachdem alle Aktivierungen und Deaktivierungen abgeschlossen sind, klickt der Benutzer auf die Schaltfläche „Berechtigungen speichern“ unter der Tabelle, um alle Berechtigungen zu speichern, die für diese Rolle aktiviert wurden.

Lassen Sie uns all diese Funktionen zur Datei roleLogic.php hinzufügen. Sie sind:

roleLogic.php:

// ... other functions up here ...
  function getAllPermissions(){
    global $conn;
    $sql = "SELECT * FROM permissions";
    $permissions = getMultipleRecords($sql);
    return $permissions;
  }

  function getRoleAllPermissions($role_id){
    global $conn;
    $sql = "SELECT permissions.* FROM permissions
            JOIN permission_role
              ON permissions.id = permission_role.permission_id
            WHERE permission_role.role_id=?";
    $permissions = getMultipleRecords($sql, 'i', [$role_id]);
    return $permissions;
  }

  function saveRolePermissions($permission_ids, $role_id) {
    global $conn;
    $sql = "DELETE FROM permission_role WHERE role_id=?";
    $result = modifyRecord($sql, 'i', [$role_id]);

    if ($result) {
      foreach ($permission_ids as $id) {
        $sql_2 = "INSERT INTO permission_role SET role_id=?, permission_id=?";
        modifyRecord($sql_2, 'ii', [$role_id, $id]);
      }
    }

    $_SESSION['success_msg'] = "Permissions saved";
    header("location: roleList.php");
    exit(0);
  }

Die Berechtigungen zum Laufen bringen

An diesem Punkt können wir die Rolle eines Benutzers bestimmen, und da die Rolle mit Berechtigungen zusammenhängt, können wir daher auch ihre Berechtigungen kennen.

Jetzt wollen wir diese Berechtigungen nutzen, d. h. sicherstellen, dass ein Administrator nur die Aktionen ausführen darf, für die er die Berechtigungen hat. Dies erreichen wir über Middleware-Funktionen. Eine Middleware ist im Grunde ein Stück Code oder eine Funktion, die ausgeführt wird, bevor eine Aktion ausgeführt wird. Typischerweise kann diese Middleware-Funktion das Verhalten der Aktion ändern oder einige Überprüfungen durchführen, die je nach den Ergebnissen der Überprüfung dazu führen können, dass die Aktion vollständig gestoppt wird.

Beispielsweise kann ein Benutzer die Berechtigungen „Post erstellen“, „Post aktualisieren“ und „Post löschen“ haben. Wenn sie angemeldet sind und versuchen, einen Beitrag zu veröffentlichen, prüft unsere Middleware-Funktion zunächst, ob dieser Benutzer die Berechtigung zum Veröffentlichen von Beiträgen hat. Wenn sie diese Berechtigung haben, gibt unsere Middleware-Funktion wahr zurück und der Beitrag wird veröffentlicht. Wenn ihnen die Berechtigung zum Veröffentlichen und Posten fehlt, leitet unsere Middleware-Funktion sie mit einer Nachricht zurück, die besagt, dass sie keine Berechtigung zum Veröffentlichen des Posts haben.

Wir werden alle unsere Middleware-Funktionen in eine einzige Datei namens middleware.php packen. Erstellen Sie es jetzt im Ordner admin und fügen Sie diesen Code dort ein:

middleware.php:

<?php

  // if user is NOT logged in, redirect them to login page
  if (!isset($_SESSION['user'])) {
    header("location: " . BASE_URL . "login.php");
  }
  // if user is logged in and this user is NOT an admin user, redirect them to landing page
  if (isset($_SESSION['user']) && is_null($_SESSION['user']['role'])) {
    header("location: " . BASE_URL);
  }
  // checks if logged in admin user can update post
  function canUpdatePost($post_id = null){
    global $conn;

    if(in_array('update-post', $_SESSION['userPermissions'])){
      if ($_SESSION['user']['role'] === "Author") { // author can update only posts that they themselves created
          $sql = "SELECT user_id FROM posts WHERE id=?";
          $post_result = getSingleRecord($sql, 'i', [$post_id]);
          $post_user_id = $post_result['user_id'];

          // if current user is the author of the post, then they can update the post
          if ($post_user_id === $user_id) {
            return true;
          } else { // if post is not created by this author
            return false;
          }
      } else { // if user is not author
        return true;
      }
    } else {
      return false;
    }
  }

  // accepts user id and post id and checks if user can publis/unpublish a post
  function canPublishPost() {
    if(in_array(['permission_name' => 'publish-post'], $_SESSION['userPermissions'])){
      // echo "<pre>"; print_r($_SESSION['userPermissions']); echo "</pre>"; die();
      return true;
    } else {
      return false;
    }
  }

  function canDeletePost() {
    if(in_array('delete-post', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canCreateUser() {
    if(in_array('create-user', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canUpdateUser() {
    if(in_array('update-user', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canDeleteUser() {
    if(in_array('delete-user', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canCreateRole($role_id) {
    if(in_array('create-role', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canUpdateRole($role_id) {
    if(in_array('update-role', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canDeleteRole($user_id, $post_id) {
    if(in_array('delete-role', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
?>
"; sterben(); gib true zurück; } Else {Rückgabe falsch; } } function canDeletePost() { if(in_array('delete-post', $_SESSION['userPermissions'])){ return true; } Else {Rückgabe falsch; } } function canCreateUser() { if(in_array('create-user', $_SESSION['userPermissions'])){ return true; } Else {Rückgabe falsch; } } function canUpdateUser() { if(in_array('update-user', $_SESSION['userPermissions'])){ return true; } Else {Rückgabe falsch; } } function canDeleteUser() { if(in_array('delete-user', $_SESSION['userPermissions'])){ return true; } Else {Rückgabe falsch; } } function canCreateRole($role_id) { if(in_array('create-role', $_SESSION['userPermissions'])){ return true; } Else {Rückgabe falsch; } } function canUpdateRole($role_id) { if(in_array('update-role', $_SESSION['userPermissions'])){ return true; } Else {Rückgabe falsch; } } function canDeleteRole($user_id, $post_id) { if(in_array('delete-role', $_SESSION['userPermissions'])){ return true; } Else {Rückgabe falsch; } }?>

Die erste if-Anweisung prüft, ob der Benutzer angemeldet ist. Wenn der Benutzer nicht angemeldet ist, wird er auf die Homepage umgeleitet. Die zweite if-Anweisung prüft, ob der Benutzer angemeldet ist und ob er/sie eine Rolle hat (ist admin). Wenn festgestellt wird, dass der Benutzer angemeldet ist und eine Rolle hat, greift er auf die Seite zu, andernfalls wird er zurück zur Startseite weitergeleitet.

In jeder Datei, auf die Sie den Zugriff von Nicht-Administratoren beschränken möchten, sollten Sie einfach diese middleware.php-Datei in diese Datei einfügen. Daher werden wir diese Datei in alle unsere Admin-Dateien aufnehmen, auf die normale Benutzer keinen Zugriff haben sollen. Öffnen Sie also alle Dateien in den beiden Ordnern im Admin-Ordner, nämlich:Benutzer, Rollen. Fügen Sie in jeder der Dateien die folgende Zeile direkt unter dem Include für config.php hinzu.

So:

<?php include('../../config.php'); ?>
<?php require_once '../middleware.php'; ?>

Und das leitet jeden Nicht-Admin-Benutzer um, der versucht, die Seite zu besuchen.

Auch in dieser middleware.php-Datei verwenden wir in_array() von PHP, um zu prüfen, ob die von uns getestete Berechtigung im Array der Berechtigungen dieses Benutzers enthalten ist. (Wenn sich ein Admin-Benutzer anmeldet, legen wir alle seine Berechtigungen in einem Sitzungsvariablen-Array namens $_SESSION['userPermissions'] ab.) Wenn sich die aktuelle Berechtigung im Array der Benutzerberechtigungen befindet, bedeutet dies, dass dieser Benutzer diese Berechtigung hat und daher gibt die Funktion wahr zurück, andernfalls gibt sie falsch zurück.

Wenn Sie nun überprüfen möchten, ob ein Benutzer eine Berechtigung hat, sagen wir, eine Berechtigung zum Veröffentlichen und Posten müssen Sie tun, indem Sie die Methode canPublishPost() wie folgt aufrufen:

<?php if (canPublishPost()): ?>
	<!-- User can publish post. Display publish post button -->
<?php else: ?>
	<!-- User cannot publish post. Do not display publish post button -->
<?php endif ?>

Auch als Middleware werden wir, bevor wir einen Beitrag aktualisieren, zuerst die Middleware-Funktion canUpdatePost() aufrufen. Wenn die Funktion prüft und feststellt, dass der Benutzer nicht über die Berechtigung zum Aktualisieren von Beiträgen verfügt, gibt sie „false“ zurück und wir können sie dann mit einer Meldung auf die Homepage umleiten, dass sie den Beitrag nicht aktualisieren darf. So:

// checks if logged in admin user can update post
function updatePost($post_values){
  global $conn;

  if(canUpdatePost($post_values['id']){
     // proceed to update post
  
  } else {
    // redirect back to homepage with message that says user is not permitted to update post
  }
}

Das Gleiche gilt für das Veröffentlichen/Nichtveröffentlichen von Beiträgen:

function togglePublishPost($post_id)
{
	if (!canPublishPost($_SESSION['user']['id'])) {
		// redirect them back to dashboard with the message that they don't have the permission to publish post
	} 
    
    // proceed to publish post

}

Jetzt bleibt uns der letzte Teil dieses Tutorials, der das Benutzerprofil aktualisiert und registrierten Benutzern die Möglichkeit gibt, ihre eigenen Konten zu löschen.

Danke fürs Folgen. Wenn Sie etwas zu sagen haben, schreiben Sie es bitte in die Kommentare.