Skip to main content

Protecting an Admin-Only Data Import Page

A role-based system must enforce permissions on the server. Hiding a link is helpful navigation, but it does not protect the page.

Store trusted session values at login

After verifying the password and retrieving the database user:

session_regenerate_id(true);
$_SESSION["user_id"] = (int) $user["user_id"];
$_SESSION["role"] = $user["role"];

The role must come from the database, not from a form field supplied by the user.

Protect the import page

Place this code before any HTML output:

<?php
session_start();

if (!isset($_SESSION["user_id"])) {
    header("Location: login.php");
    exit;
}

if (($_SESSION["role"] ?? "") !== "admin") {
    http_response_code(403);
    exit("You do not have permission to access this page.");
}

Protect processing as well as display

The role check must run on the script that processes the uploaded CSV. A user can send a request directly even when the navigation link is hidden.

You may keep the form and processing in one protected file or require the same protection file from both scripts.

Show navigation by role

<?php if (($_SESSION["role"] ?? "") === "admin"): ?>
  <a href="import.php">Import dataset</a>
<?php endif; ?>

This improves usability but is not the security control.

Test the access rules

Test Expected result
Logged out user opens import URL Redirected to login
Standard user opens import URL 403 response
Administrator opens import URL Upload form appears
Standard user submits directly Request rejected
Changed browser role field No effect because role comes from session

Check

  • Sessions start before output.
  • Login and role are checked server-side.
  • Processing route repeats the protection.
  • Roles come from stored user records.
  • Tests include direct URL access.
  • Test accounts and data are fictional.