Web-based Secure Notes App PHP, MySQL
👤 Sharing: AI
Okay, here's a basic example of a web-based secure notes app using PHP and MySQL. It covers the core functionalities of creating, reading, updating, and deleting notes (CRUD), along with basic user authentication (registration and login). It prioritizes demonstrating the logic rather than focusing on advanced security measures (which would require a much more extensive implementation). **Please understand that this is a simplified example and should not be used in a production environment without significant security enhancements.**
**Important Security Note:** This example does NOT include proper input sanitization, output escaping, password hashing with salts, protection against CSRF/XSS attacks, or other critical security measures. **Treat this as a starting point for learning, not a secure application.** In a real-world application, you *must* address these vulnerabilities.
**Conceptual Overview:**
1. **Database Setup:** We'll need a MySQL database to store user accounts and notes.
2. **User Authentication:**
* Registration: Allows users to create accounts.
* Login: Authenticates users to access their notes.
* Session Management: Maintains user login state.
3. **Note Management:**
* Create: Adds a new note to the database.
* Read: Displays a user's notes.
* Update: Allows editing an existing note.
* Delete: Removes a note.
**File Structure:**
```
secure_notes_app/
??? config.php # Database connection and configuration
??? register.php # User registration
??? login.php # User login
??? logout.php # User logout
??? dashboard.php # Main notes dashboard
??? create_note.php # Create a new note
??? edit_note.php # Edit an existing note
??? delete_note.php # Delete a note
??? styles.css # Simple CSS styling (optional)
```
**1. `config.php` (Database Configuration):**
```php
<?php
// Database credentials
define('DB_HOST', 'localhost');
define('DB_USER', 'your_db_user');
define('DB_PASS', 'your_db_password');
define('DB_NAME', 'your_db_name');
// Create connection
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
session_start(); // Start the session for user management
?>
```
* **Explanation:** This file establishes a connection to your MySQL database. Replace the placeholder values with your actual database credentials. It also starts a PHP session, which is used to track the user's login status across different pages. `define()` is used to create constant values for the database connection details.
**2. `register.php` (User Registration):**
```php
<?php
require_once('config.php');
$error = '';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
$password = $_POST['password']; // In a real app, use password_hash()
// Basic validation (add more robust validation)
if (empty($username) || empty($password)) {
$error = "Please fill in all fields.";
} else {
// Check if username already exists
$sql = "SELECT id FROM users WHERE username = '$username'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
$error = "Username already exists.";
} else {
// Insert new user (INSECURE: Use prepared statements)
$sql = "INSERT INTO users (username, password) VALUES ('$username', '$password')"; //In real app use password_hash()
if ($conn->query($sql) === TRUE) {
header("Location: login.php"); // Redirect to login page
exit();
} else {
$error = "Error creating account: " . $conn->error;
}
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Register</h1>
<?php if ($error) echo "<p style='color:red;'>$error</p>"; ?>
<form method="post">
Username: <input type="text" name="username"><br><br>
Password: <input type="password" name="password"><br><br>
<input type="submit" value="Register">
</form>
<p>Already have an account? <a href="login.php">Login</a></p>
</body>
</html>
```
* **Explanation:**
* Includes `config.php` to establish the database connection.
* Handles form submission (`$_SERVER["REQUEST_METHOD"] == "POST"`).
* Retrieves username and password from the form.
* **Validation:** Performs basic checks for empty fields. *Important:* Add more robust validation to prevent injection attacks.
* **Username Existence Check:** Queries the database to see if the username is already taken.
* **User Insertion:** If the username is unique, inserts the new user into the `users` table. **Important:** This is highly insecure! Use prepared statements to prevent SQL injection. Also, `password` should be replaced with `password_hash($password, PASSWORD_DEFAULT)` to store the password securely.
* **Redirection:** Redirects the user to the `login.php` page upon successful registration.
* **HTML Form:** Displays a registration form.
**3. `login.php` (User Login):**
```php
<?php
require_once('config.php');
$error = '';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST['username'];
$password = $_POST['password'];
// Basic validation (add more robust validation)
if (empty($username) || empty($password)) {
$error = "Please fill in all fields.";
} else {
// Query the database to find the user
$sql = "SELECT id, username, password FROM users WHERE username = '$username'";
$result = $conn->query($sql);
if ($result->num_rows == 1) {
$row = $result->fetch_assoc();
// Verify password (INSECURE: Use password_verify())
if ($password == $row['password']) { // Insecure: should use password_verify
$_SESSION['user_id'] = $row['id'];
$_SESSION['username'] = $row['username'];
header("Location: dashboard.php"); // Redirect to dashboard
exit();
} else {
$error = "Incorrect password.";
}
} else {
$error = "Invalid username.";
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Login</h1>
<?php if ($error) echo "<p style='color:red;'>$error</p>"; ?>
<form method="post">
Username: <input type="text" name="username"><br><br>
Password: <input type="password" name="password"><br><br>
<input type="submit" value="Login">
</form>
<p>Don't have an account? <a href="register.php">Register</a></p>
</body>
</html>
```
* **Explanation:**
* Includes `config.php`.
* Handles form submission.
* Retrieves username and password.
* **Validation:** Checks for empty fields. *Important:* Add more robust validation.
* **User Query:** Queries the database to find the user with the given username.
* **Password Verification:** Checks if the entered password matches the stored password. **Important:** This is insecure! Use `password_verify($password, $hashed_password)` to securely compare the entered password with the hashed password stored in the database.
* **Session Management:** If the login is successful, sets the `user_id` and `username` in the `$_SESSION` array.
* **Redirection:** Redirects to the `dashboard.php` page.
* **HTML Form:** Displays the login form.
**4. `logout.php` (User Logout):**
```php
<?php
require_once('config.php');
// Unset all of the session variables.
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Finally, destroy the session.
session_destroy();
header("Location: login.php"); // Redirect to login page
exit();
?>
```
* **Explanation:** This script destroys the session, effectively logging the user out. It removes all session variables and redirects the user back to the login page.
**5. `dashboard.php` (Notes Dashboard):**
```php
<?php
require_once('config.php');
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
$user_id = $_SESSION['user_id'];
// Fetch notes from the database
$sql = "SELECT id, title, content FROM notes WHERE user_id = '$user_id'";
$result = $conn->query($sql);
?>
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Welcome, <?php echo $_SESSION['username']; ?>!</h1>
<p><a href="logout.php">Logout</a></p>
<p><a href="create_note.php">Create New Note</a></p>
<h2>Your Notes:</h2>
<?php
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "<div>";
echo "<h3>" . htmlspecialchars($row['title']) . "</h3>"; // Escape output!
echo "<p>" . htmlspecialchars($row['content']) . "</p>"; // Escape output!
echo "<a href='edit_note.php?id=" . $row['id'] . "'>Edit</a> | ";
echo "<a href='delete_note.php?id=" . $row['id'] . "'>Delete</a>";
echo "</div><br>";
}
} else {
echo "<p>No notes found.</p>";
}
?>
</body>
</html>
```
* **Explanation:**
* Includes `config.php`.
* **Authentication Check:** Ensures that the user is logged in by checking for the `user_id` in the session. If not logged in, redirects to `login.php`.
* **Fetching Notes:** Retrieves the user's notes from the database.
* **Displaying Notes:** Iterates through the results and displays the notes. *Important:* Uses `htmlspecialchars()` to escape output, preventing XSS attacks.
* Provides links to `edit_note.php` and `delete_note.php` for each note.
**6. `create_note.php` (Create a New Note):**
```php
<?php
require_once('config.php');
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
$user_id = $_SESSION['user_id'];
$error = '';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$title = $_POST['title'];
$content = $_POST['content'];
// Basic validation (add more robust validation)
if (empty($title) || empty($content)) {
$error = "Please fill in all fields.";
} else {
// Insert note into the database (INSECURE: Use prepared statements)
$sql = "INSERT INTO notes (user_id, title, content) VALUES ('$user_id', '$title', '$content')";
if ($conn->query($sql) === TRUE) {
header("Location: dashboard.php"); // Redirect to dashboard
exit();
} else {
$error = "Error creating note: " . $conn->error;
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Create Note</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Create New Note</h1>
<?php if ($error) echo "<p style='color:red;'>$error</p>"; ?>
<form method="post">
Title: <input type="text" name="title"><br><br>
Content: <textarea name="content" rows="5" cols="40"></textarea><br><br>
<input type="submit" value="Create Note">
</form>
<p><a href="dashboard.php">Back to Dashboard</a></p>
</body>
</html>
```
* **Explanation:**
* Includes `config.php`.
* Authentication check.
* Handles form submission.
* Retrieves title and content from the form.
* **Validation:** Checks for empty fields. *Important:* Add more robust validation and escaping!
* **Note Insertion:** Inserts the new note into the `notes` table. **Important:** This is insecure! Use prepared statements to prevent SQL injection.
* Redirects to `dashboard.php` upon success.
* Displays the note creation form.
**7. `edit_note.php` (Edit an Existing Note):**
```php
<?php
require_once('config.php');
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
$user_id = $_SESSION['user_id'];
// Get note ID from the URL
if (isset($_GET['id']) && is_numeric($_GET['id'])) {
$note_id = $_GET['id'];
// Fetch the note from the database
$sql = "SELECT id, title, content FROM notes WHERE id = '$note_id' AND user_id = '$user_id'";
$result = $conn->query($sql);
if ($result->num_rows == 1) {
$row = $result->fetch_assoc();
$title = $row['title'];
$content = $row['content'];
} else {
// Note not found or not owned by user
header("Location: dashboard.php");
exit();
}
} else {
// Invalid note ID
header("Location: dashboard.php");
exit();
}
$error = '';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$title = $_POST['title'];
$content = $_POST['content'];
// Basic validation (add more robust validation)
if (empty($title) || empty($content)) {
$error = "Please fill in all fields.";
} else {
// Update note in the database (INSECURE: Use prepared statements)
$sql = "UPDATE notes SET title = '$title', content = '$content' WHERE id = '$note_id' AND user_id = '$user_id'";
if ($conn->query($sql) === TRUE) {
header("Location: dashboard.php"); // Redirect to dashboard
exit();
} else {
$error = "Error updating note: " . $conn->error;
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Edit Note</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Edit Note</h1>
<?php if ($error) echo "<p style='color:red;'>$error</p>"; ?>
<form method="post">
Title: <input type="text" name="title" value="<?php echo htmlspecialchars($title); ?>"><br><br>
Content: <textarea name="content" rows="5" cols="40"><?php echo htmlspecialchars($content); ?></textarea><br><br>
<input type="submit" value="Update Note">
</form>
<p><a href="dashboard.php">Back to Dashboard</a></p>
</body>
</html>
```
* **Explanation:**
* Includes `config.php`.
* Authentication check.
* Retrieves the note ID from the URL (`$_GET['id']`).
* **Note Retrieval:** Fetches the note from the database based on the ID and user ID. Checks if the note exists and belongs to the user.
* If the note is found, populates the form with the existing note data.
* Handles form submission.
* Retrieves the updated title and content.
* **Validation:** Checks for empty fields. *Important:* Add more robust validation and escaping.
* **Note Update:** Updates the note in the database. **Important:** This is insecure! Use prepared statements.
* Redirects to `dashboard.php` upon success.
**8. `delete_note.php` (Delete a Note):**
```php
<?php
require_once('config.php');
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
exit();
}
$user_id = $_SESSION['user_id'];
// Get note ID from the URL
if (isset($_GET['id']) && is_numeric($_GET['id'])) {
$note_id = $_GET['id'];
// Delete the note from the database (INSECURE: Use prepared statements)
$sql = "DELETE FROM notes WHERE id = '$note_id' AND user_id = '$user_id'";
if ($conn->query($sql) === TRUE) {
header("Location: dashboard.php"); // Redirect to dashboard
exit();
} else {
echo "Error deleting note: " . $conn->error;
}
} else {
// Invalid note ID
header("Location: dashboard.php");
exit();
}
?>
```
* **Explanation:**
* Includes `config.php`.
* Authentication check.
* Retrieves the note ID from the URL.
* **Note Deletion:** Deletes the note from the database based on the ID and user ID. **Important:** This is insecure. Use prepared statements.
* Redirects to `dashboard.php`.
**9. `styles.css` (Optional):**
```css
body {
font-family: sans-serif;
}
h1, h2 {
color: #333;
}
form {
margin-bottom: 20px;
}
input[type="text"],
input[type="password"],
textarea {
padding: 5px;
border: 1px solid #ccc;
border-radius: 4px;
}
input[type="submit"] {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
a {
color: #007bff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.error {
color: red;
}
```
* **Explanation:** A simple CSS file to style the pages. This is optional but improves the visual appearance.
**MySQL Database Setup:**
You'll need to create a database named `your_db_name` (or whatever you defined in `config.php`) and two tables: `users` and `notes`. Here's the SQL to create the tables:
```sql
CREATE DATABASE IF NOT EXISTS your_db_name;
USE your_db_name;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL -- Store hashed passwords in a real app
);
CREATE TABLE notes (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
title VARCHAR(255) NOT NULL,
content TEXT,
FOREIGN KEY (user_id) REFERENCES users(id)
);
```
**How to Run:**
1. Save the PHP files in a directory on your web server (e.g., `secure_notes_app`).
2. Create the database and tables using the SQL above.
3. Configure the database credentials in `config.php`.
4. Access the `register.php` page in your browser (e.g., `http://localhost/secure_notes_app/register.php`).
**Key Improvements for a Real Application (Security):**
* **Prepared Statements:** Use prepared statements with parameterized queries in all database interactions to prevent SQL injection. This is *critical*. Example:
```php
$stmt = $conn->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
$stmt->bind_param("ss", $username, $hashed_password); // "ss" for two strings
$stmt->execute();
```
* **Password Hashing:** Store passwords using `password_hash()` with a strong algorithm like `PASSWORD_DEFAULT`. Use `password_verify()` to compare entered passwords with the stored hashes. NEVER store passwords in plain text!
* **Input Sanitization/Validation:** Thoroughly sanitize and validate all user input to prevent XSS and other attacks. Use functions like `htmlspecialchars()` for output escaping. Consider using libraries like `filter_var()` for input validation.
* **Output Escaping:** Always escape output using `htmlspecialchars()` to prevent XSS attacks.
* **CSRF Protection:** Implement Cross-Site Request Forgery (CSRF) protection using tokens.
* **Session Security:** Configure your PHP session settings for increased security (e.g., `session.cookie_secure`, `session.cookie_httponly`).
* **Error Handling:** Implement proper error handling and logging, but avoid displaying sensitive information to the user.
* **HTTPS:** Always use HTTPS to encrypt communication between the client and server.
* **Rate Limiting:** Implement rate limiting to prevent brute-force attacks on login forms.
* **Regular Security Audits:** Conduct regular security audits to identify and address potential vulnerabilities.
This is a simplified starting point. Building a secure web application requires a deep understanding of security principles and best practices. Remember to prioritize security in every stage of development.
👁️ Viewed: 11
Comments