This zone is sleeping right now! ZzzZZzzz

Better not distrub it! ~You go to the petrol station and buy a slushy instead, everything is cool!~

This area will open again in 000.beats!

(Learn about Swatch Time)

Some other zones are awake :^]


Chat Artifacts Gallery Guilds Search Wiki Login Register

Welcome, Guest. Please login or register. - Thinking of joining the forum??
May 11, 2026 - @308.72 (what is this?)
Activity rating: Three Stars Posts & Arts: 37/1k.beats Random | Recent Posts | Guild Recents
News: :sleep: These are fast times on the World Wide Web~ Guild Events: Spring Themed Projects

+  MelonLand Forum
|-+  Life & The Web
| |-+  ✁ ∙ Web Crafting
| | |-+  ☔︎ ∙ I need Help!
| | | |-+  PHP Help - Admin only login not working.


« previous next »
Pages: [1] Print Embed
Author Topic: PHP Help - Admin only login not working.  (Read 78 times)
clownvomitz
Casual Poster ⚓︎
*
View Profile WWW


they/he/it
⛺︎ My Room
StatusCafe: clownvomitz
iMood: clownvomitz
RSS: RSS

Guild Memberships:
Artifacts:
Joined 2026!
« on: May 10, 2026 @609.19 » Embed

Hi there! So for some context I got a free domain running on Altervista to try and prepare myself before swapping to a self-hosted domain through a VPS. I wanted top dip my toes into some PHP before I made the leap before I truly made a full swap, and so far I love it! HOWEVER, the scripts I am using both have the same issue and I wanted to see if someone knowledgeable could help me out?

I am using both the simple rss updater and blog script from ophanimkei.com. the codes work fine for the most part, everything works EXCEPT for the secure log in feature. all scripts are available F2U on ophanimkei's github.

so, how this works is you're supposed to have a little log in screen before you can make a blog post / rss update to keep it secure. however, when i try to type in my log in information i created, the log in screen just refreshes. no error, no nothing. it won't give me access to the post screen. it's gotten to the point where if i wanna make a blog post i just delete the checkLogin and require_once function to just put a little post up then pout it back bc at least then i know no one can get in once i'm done haha. but that's still a hassle.

is there any way to fix this or an alternative script I could possible plug in to help? or is it because i'm hosting through Altervista for some reason? i really do love how everything looks and works with these scripts, because literally everything else is perfect, it's just the log in giving me trouble.

The login code is exactly the same for both scripts, so I will be showing you the script for the blog specifically.

auth.php, used for log in info and stuff
Code
<?php
session_start();

// ===== Single User Configuration =====
$username = 'admin';  // Change this to whatever you want
$password_hash = 'pass';  // Change this. Should be hashed but accepts plaintext (really recommend only doing that for testing)
// ====================================

function check_login() {
    global $username, $password_hash;

    if (!isset($_SESSION['logged_in'])) {
        if (isset($_POST['username']) && isset($_POST['password'])) {
            // Verify password with password_verify()
            if ($_POST['username'] === $username && password_verify($_POST['password'], $password_hash)) {
                $_SESSION['logged_in'] = true;
                return true;
            }
        }

        show_login_form();
        exit;
    }
    return true;
    exit;
}


function show_login_form() {
    echo '
    <!DOCTYPE html>
    <html>
    <head>
        <title>Login</title>
        <style>
            body {
                background-color: #f5f5f5;
                color: #333;
                font-family: "MS PGothic", "Osaka", Arial, sans-serif;
                font-size: 14px;
                line-height: 1.6;
                margin: 0;
                padding: 0;
                background-image:url("images/wallpaperghibli.jpg");
            }

            p {
                margin: 3px;
                padding: 0px;
            }
            .login-container {
                max-width: 300px;
                margin: 50px auto;
                padding: 20px;
                background: white;
                box-shadow: 0 0 10px rgba(0,0,0,0.1);
            }
            .login-container input {
                width: 100%;
                padding: 10px;
                margin-bottom: 15px;
                border: 1px solid #ddd;
                border-radius: 3px;
                box-sizing: border-box;
            }
            .login-container button {
                width: 100%;
                padding: 10px;
                background-color:rgb(144, 236, 255);
                color: white;
                border: none;
                border-radius: 3px;
                cursor: pointer;
            }
        </style>
    </head>
    <body>
        <div class="login-container">
            <h2>Login</h2>
            <form method="post">
                <input type="text" name="username" placeholder="Username" required>
                <input type="password" name="password" placeholder="Password" required>
                <button type="submit">Login</button>
            </form>
        </div>
    </body>
    </html>';
}
?>

admin.php for creating the blog post itself in browser

Code
<?php
require_once 'auth.php';
check_login(); // This will show login form if not logged in

?>

<?php
session_start();

// ===== Configuration =====
$upload_dir = 'uploads/';
$allowed_types = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
// ========================

// Initialize database connection
include 'config.php'; // <-- THIS WAS MISSING!

// Limit how many posts show in dropdown
$limit = 10;

try {
    $stmt = $pdo->query("
        SELECT id, title, visible, post_date 
        FROM logs 
        ORDER BY post_date DESC 
        LIMIT $limit
    ");
    $posts = $stmt->fetchAll(PDO::FETCH_ASSOC);

    // Count hidden posts for info
    $totalPosts = $pdo->query("SELECT COUNT(*) FROM logs")->fetchColumn();
    $hiddenCount = max(0, $totalPosts - $limit);
} catch (PDOException $e) {
    $posts = [];
    $hiddenCount = 0;
}


if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['image'])) {
    $file = $_FILES['image'];
    
    // Validate
    if (!in_array($file['type'], $allowed_types)) {
        $error = 'Only JPG, PNG, and GIF allowed.';
    } elseif ($file['size'] > $max_size) {
        $error = 'File too large (max 2MB).';
    } else {
        // Preserve original filename (sanitized)
        $filename = preg_replace('/[^a-z0-9_.-]/i', '_', basename($file['name']));
        $destination = $upload_dir . $filename;
        
        // Handle duplicates
        $counter = 1;
        while (file_exists($destination)) {
            $filename = pathinfo($file['name'], PATHINFO_FILENAME) . "_$counter." . pathinfo($file['name'], PATHINFO_EXTENSION);
            $destination = $upload_dir . $filename;
            $counter++;
        }
        
        // Compress while preserving name
        if ($file['type'] === 'image/jpeg') {
            $image = imagecreatefromjpeg($file['tmp_name']);
            imagejpeg($image, $destination, 85); // 85% quality
        } elseif ($file['type'] === 'image/png') {
            $image = imagecreatefrompng($file['tmp_name']);
            imagepng($image, $destination, 8); // 80% compression
        } else {
            move_uploaded_file($file['tmp_name'], $destination);
        }
        
        if (isset($image)) imagedestroy($image);
        $image_url = $destination;
    }

}


//===============================

// Handle image upload
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['image'])) {
    // ... [keep your existing image upload code] ...
}

// Handle post submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['title'])) {
    try {
        $content = $_POST['content'];
        $post_date = !empty($_POST['post_date']) ? $_POST['post_date'] : date('Y-m-d H:i:s');
        $edit_id = $_POST['edit_id'] ?? '';

        if (!empty($edit_id)) {
            // --- Update existing post ---
            $stmt = $pdo->prepare("
                UPDATE logs
                SET title = ?, content = ?, post_date = ?, category = ?, tags = ?, anchor_name = ?, visible = ?
                WHERE id = ?
            ");
            $stmt->execute([
                $_POST['title'],
                $content,
                $post_date,
                $_POST['category'] ?? 'Uncategorized',
                $_POST['tags'] ?? '',
                $_POST['anchor_name'] ?? '',
                $_POST['visible'] ?? 'n',
                $edit_id
            ]);

            // Redirect to avoid TinyMCE reset
            header('Location: admin.php?success=updated');
            exit;
        } else {
            // --- Create new post ---
            $stmt = $pdo->prepare("
                INSERT INTO logs (title, content, post_date, category, tags, anchor_name, visible)
                VALUES (?, ?, ?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                $_POST['title'],
                $content,
                $post_date,
                $_POST['category'] ?? 'Uncategorized',
                $_POST['tags'] ?? '',
                $_POST['anchor_name'] ?? '',
                $_POST['visible'] ?? 'n'
            ]);

            // Redirect to avoid TinyMCE reset
            header('Location: admin.php?success=published');
            exit;
        }
    } catch (PDOException $e) {
        die("Database error: " . $e->getMessage());
    }
}


?>



<!DOCTYPE html>
<html>
<head>
    <title>Admin Panel</title>
     <link rel="stylesheet" href="style.css">
    <style>
        
        body { 
            font-family: Arial, sans-serif; 
            max-width: 800px; 
            margin: 0 auto;  }
            
        textarea { 
            width: 96%; 
            height: 300px; 
            
        }
        
        .image-preview  { 
        max-width: 200px; 
        display: block; 
        margin: 10px 0; 
            
        }
        
        .container {
        background-color: white;
        padding: 8px;
        background-repeat:repeat-y;
        min-height: 100vh;
        }
        .
    </style>
</head>

<body>
    
    <div class="container">
    <?php if (!empty($_GET['success'])): ?>
    <div class="success">
        <?php 
        if ($_GET['success'] === 'published') echo '✅ Post published!';
        elseif ($_GET['success'] === 'updated') echo '✅ Post updated!';
        ?>
    </div>
        <?php endif; ?>


        <?php
        // Fetch posts
        $stmt = $pdo->query("SELECT id, title, visible, post_date FROM logs ORDER BY post_date DESC");
        $posts = $stmt->fetchAll(PDO::FETCH_ASSOC);
        ?>

        
        <?php
        $editing = false;
        $edit_post = null;

        if (isset($_GET['edit'])) {
            $editing = true;
            $id = (int)$_GET['edit'];
            $stmt = $pdo->prepare("SELECT * FROM logs WHERE id = ?");
            $stmt->execute([$id]);
            $edit_post = $stmt->fetch(PDO::FETCH_ASSOC);
        }
        ?>


        <form method="post" enctype="multipart/form-data">

        <p>

            <label>Edit existing post:<br>
                <select name="edit_id" onchange="loadPost(this.value)">
                <option value="">— New Post —</option>
                <optgroup label="Drafts">
                    <?php foreach ($posts as $p): ?>
                    <?php if ($p['visible'] == 'n'): ?>
                        <option value="<?= htmlspecialchars($p['id']) ?>">
                        <?= htmlspecialchars($p['title']) ?> (<?= htmlspecialchars($p['post_date']) ?>)
                        </option>
                    <?php endif; ?>
                    <?php endforeach; ?>
                </optgroup>
                    <optgroup label="Published">
                        <?php foreach ($posts as $p): ?>
                            <?php if ($p['visible'] == 'y'): ?>
                                <option value="<?= htmlspecialchars($p['id']) ?>">
                                    <?= htmlspecialchars($p['title']) ?> (<?= htmlspecialchars($p['post_date']) ?>)
                                </option>
                            <?php endif; ?>
                        <?php endforeach; ?>

                        <?php if ($hiddenCount > 0): ?>
                            <option disabled>+<?= $hiddenCount ?> more posts...</option>
                        <?php endif; ?>
                    </optgroup>
                </select>
            </label>
            </p>
            <p>
                <label>Title:<br>
                <input type="text" name="title" required style="width:96%"
                    value="<?= htmlspecialchars($edit_post['title'] ?? '') ?>">
                </label>
            </p>
            
            <p>
                <label>Content (HTML):<br>
                <textarea id="editor" name="content"><?= htmlspecialchars($edit_post['content'] ?? '') ?></textarea>
                </label>
            </p>
            
            </center>
            
            <p>
                <label>Date:<br>
                <input type="datetime-local" name="post_date"
       value="<?= isset($edit_post['post_date']) ? date('Y-m-d\TH:i', strtotime($edit_post['post_date'])) : '' ?>">
                </label>
            </p>
            
            <p>
                <label>Tags (comma-separated):<br>
                <input type="text" name="tags" placeholder="personal, diary, memories"
       value="<?= htmlspecialchars($edit_post['tags'] ?? '') ?>">
                </label>
            </p>

            <p>

            <label>Status:<br>
                <select name="visible">
                 <option value="n" <?= (isset($edit_post['visible']) && $edit_post['visible'] === 'n') ? 'selected' : '' ?>>Draft (Not Visible)</option>
                 <option value="y" <?= (isset($edit_post['visible']) && $edit_post['visible'] === 'y') ? 'selected' : '' ?>>Published (Visible)</option>
                </select>
            </label>
            </p>
            
            <button type="submit">Publish</button>
        </form>
    </div>

    
    
        <script>
        function insertImage() {
            const url = prompt("Paste image URL:");
            if (url) {
                document.querySelector('textarea').value += \n<img src="${url}">\n;
            }
        }
        </script>
        
        <?php include "tinycme.js"?>
<script>
  tinymce.init({
    selector: '#editor',
    plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount',
    toolbar: 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table | align lineheight | numlist bullist indent outdent | emoticons charmap | removeformat',
    images_upload_url: 'upload.php', // Your image upload endpoint
    automatic_uploads: true,
    images_upload_handler: function (blobInfo, progress) {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.withCredentials = false;
        xhr.open('POST', 'upload.php');
        
        xhr.upload.onprogress = function (e) {
          progress(e.loaded / e.total * 100);
        };
        
        xhr.onload = function() {
          if (xhr.status < 200 || xhr.status >= 300) {
            reject('HTTP Error: ' + xhr.status);
            return;
          }
          
          const json = JSON.parse(xhr.responseText);
          if (!json || typeof json.location != 'string') {
            reject('Invalid JSON: ' + xhr.responseText);
            return;
          }
          
          resolve(json.location);
        };
        
        xhr.onerror = function () {
          reject('Image upload failed due to a XHR Transport error. Status: ' + xhr.status);
        };
        
        const formData = new FormData();
        formData.append('file', blobInfo.blob(), blobInfo.filename());
        
        xhr.send(formData);
      });
    }
  });
</script>
<script>
    function loadPost(id) {
    const title = document.querySelector('[name="title"]');
    const editor = tinymce.get('editor');
    const date = document.querySelector('[name="post_date"]');
    const tags = document.querySelector('[name="tags"]');
    const visible = document.querySelector('[name="visible"]');

    if (!id) {
        // 🧹 clear everything for a new post
        title.value = '';
        editor.setContent('');
        date.value = '';
        tags.value = '';
        visible.value = 'n';
        return;
    }

    // otherwise load existing post
    fetch('load_post.php?id=' + id)
        .then(r => r.json())
        .then(post => {
        title.value = post.title;
        editor.setContent(post.content);
        date.value = post.post_date.replace(' ', 'T');
        tags.value = post.tags;
        visible.value = post.visible;
        });
    }

</script>

<script>
window.onbeforeunload = function (e) {
    e = e || window.event;

    // For IE and Firefox prior to version 4
    if (e) {
        e.returnValue = 'Sure?';
    }

    // For Safari
    return 'Sure?';
};
</script>

</body>
</html>

thank you for reading! if you need any more info pls let me know. ive been trying to cram as much info in my brain regarding learning php in the last weeks just to never get this working LOL.
Logged

https://file.garden/ZpyoPBriBHjSP-h5/nb.gifvhttps://file.garden/ZpyoPBriBHjSP-h5/hb.gifv
https://adriansblinkiecollection.neocities.org/e65.gifhttps://adriansblinkiecollection.neocities.org/e48.gif
"sunrise, parabellum"

Artifact Swap: Batman Spiffo
Dan Q
Hero Member ⚓︎
*****
View Profile WWWArt


I have no idea what I am doing
⛺︎ My Room
RSS: RSS

Guild Memberships:
« Reply #1 on: May 10, 2026 @626.53 » Embed

A few quick things to try before we get deeper:

1. The session_start() in admin.php is redundant and potentially problematic; the one from auth.php (which is loaded by require_once) has already taken effect. Starting a new session destroys the one created by check_login(), invalidating your session and logging you out. This is probably the problem!

2. Closing your PHP tag ?> and then re-opening them <?php with anything in-between them, EVEN WHITESPACE, can prevent PHP sending headers. Headers like Cookie: headers, which are needed for sessions. It's probably not this, but remove the closer and the opener in admin.php before the session_start() you just removed. Similarly, you might like to remove the ?> at the end of auth.php - it's not necessary to close PHP tags at the end of a file, and it increases the risk that you accidentally introduce unwanted whitespace after it.




If that's not it, the next step is probably to do some debugging. "Hello-type" debugging will probably do, e.g. you might like to add some code like this after the check_login() in admin.php:

Code
print_r($_POST); // see that your username and password are being received by PHP correctly
echo '<br>';
print_r($_SESSION); // see what your session contains
die(); // stop processing

See if that gives any clues.

But my gut says that it's the double-session_start() problem.
Logged

https://danq.me/_q26t/badges/dan-q-88x31-lighter.gif https://danq.me/_q26t/badges/dan-q-88x31-peekaboo-scroller.gif https://beige-buttons.danq.dev/beige-buttons-88x31.gif https://embed-html.danq.dev/embed-html-88x31.gif

Artifact Swap: I met Dan Q on Melonland!PolyamorousBouncy Egg!Joined 2025!Lurby
clownvomitz
Casual Poster ⚓︎
*
View Profile WWW


they/he/it
⛺︎ My Room
StatusCafe: clownvomitz
iMood: clownvomitz
RSS: RSS

Guild Memberships:
Artifacts:
Joined 2026!
« Reply #2 on: May 10, 2026 @648.78 » Embed

@Dan Q

Hi there! Thank you for your reply!

I deleted the extra session_start() and it sadly didn't work. i added the snippet you posted after check_login(); in admin.php as well and nothing changed. all i see is the log in form from auth.php and it just refreshes and nothing changes. no errors or anything like that.  :ohdear:
Logged

https://file.garden/ZpyoPBriBHjSP-h5/nb.gifvhttps://file.garden/ZpyoPBriBHjSP-h5/hb.gifv
https://adriansblinkiecollection.neocities.org/e65.gifhttps://adriansblinkiecollection.neocities.org/e48.gif
"sunrise, parabellum"

Artifact Swap: Batman Spiffo
Dan Q
Hero Member ⚓︎
*****
View Profile WWWArt


I have no idea what I am doing
⛺︎ My Room
RSS: RSS

Guild Memberships:
« Reply #3 on: May 10, 2026 @657.36 » Embed

i added the snippet you posted after check_login(); in admin.php as well and nothing changed

Oh! Of course it won't; sorry! There are exit; statements in check_login() that mean we'll never get that far.

You might get better results by putting that debug code at the top of auth.php.

But meanwhile, I've seen a bigger issue! $password_hash is expected to contain the HASH of a password, not a password. The flow runs like this:

- user enters a password, e.g. 'pass'
- that gets hashed with the same parameters as the hashed password, giving some long garbled string
- that garbled string gets compared to the value of $password_hash; if they match, they get to log in

As a quick check (don't use this "for real"!), try changing:


Code
if ($_POST['username'] === $username && password_verify($_POST['password'], $password_hash)) {

to:

Code
if ($_POST['username'] === $username && $_POST['password'] === $password_hash) {

This skips the hashing (one-way encryption) stage entirely and means that the password really is 'pass'.

If that fixes it, then when you put it back to normal you need to store a HASH, not a password, in the $password_hash variable.

Logged

https://danq.me/_q26t/badges/dan-q-88x31-lighter.gif https://danq.me/_q26t/badges/dan-q-88x31-peekaboo-scroller.gif https://beige-buttons.danq.dev/beige-buttons-88x31.gif https://embed-html.danq.dev/embed-html-88x31.gif

Artifact Swap: I met Dan Q on Melonland!PolyamorousBouncy Egg!Joined 2025!Lurby
Dan Q
Hero Member ⚓︎
*****
View Profile WWWArt


I have no idea what I am doing
⛺︎ My Room
RSS: RSS

Guild Memberships:
« Reply #4 on: May 10, 2026 @660.54 » Embed

If I'm right, here's an example value for $password_hash that would match the password 'pass':

Code
$password_hash = '$2y$12$IU9LceRPV8mwPSs53JVy9.CyLtOeUcww93qOFAF0i7XOItN1a9VFe';

That's the password 'pass', hashed using the BCrypt algorithm (that's what the $2y means) with 12 rounds of complexity (that's what the $12 means).

You can generate your own password hashes in PHP using password_hash(). For example, this is the code I used to generate the string above:


Code
<?php
echo password_hash('pass', PASSWORD_DEFAULT);
Logged

https://danq.me/_q26t/badges/dan-q-88x31-lighter.gif https://danq.me/_q26t/badges/dan-q-88x31-peekaboo-scroller.gif https://beige-buttons.danq.dev/beige-buttons-88x31.gif https://embed-html.danq.dev/embed-html-88x31.gif

Artifact Swap: I met Dan Q on Melonland!PolyamorousBouncy Egg!Joined 2025!Lurby
clownvomitz
Casual Poster ⚓︎
*
View Profile WWW


they/he/it
⛺︎ My Room
StatusCafe: clownvomitz
iMood: clownvomitz
RSS: RSS

Guild Memberships:
Artifacts:
Joined 2026!
« Reply #5 on: May 10, 2026 @665.93 » Embed

@Dan Q IT WORKS!!!!!
THANK YOU SO MUCH!! This has been killing me for WEEKS! THANK YOU!!!  :ha:

In a similar vein, I fully don't understand how hashed passwords would work in this sense. Do you know a way I'd be able to use hashed passwords for these log ins securely?

THANK YOU again!!  :4u:
Logged

https://file.garden/ZpyoPBriBHjSP-h5/nb.gifvhttps://file.garden/ZpyoPBriBHjSP-h5/hb.gifv
https://adriansblinkiecollection.neocities.org/e65.gifhttps://adriansblinkiecollection.neocities.org/e48.gif
"sunrise, parabellum"

Artifact Swap: Batman Spiffo
Dan Q
Hero Member ⚓︎
*****
View Profile WWWArt


I have no idea what I am doing
⛺︎ My Room
RSS: RSS

Guild Memberships:
« Reply #6 on: May 10, 2026 @680.06 » Embed

In a similar vein, I fully don't understand how hashed passwords would work in this sense. Do you know a way I'd be able to use hashed passwords for these log ins securely?

Hashed passwords improve security in two distinct ways.

Why your passwords should be hashed; reason 1

The first way is that exposing the hash does not expose the password. This is useful because people re-use passwords (even though security researchers like me tell them they shouldn't!). Like: suppose you use 'hunter2' as your password everywhere: your online banking, your email, and now your website. Suppose I break in to your webserver and read the PHP code. If it says $password = 'hunter2', then I now know your password and I can use it to break in to all of your other accounts too. It's going to be a bad day for you! But because you store a hash instead of the password, I can't work out your actual password. Hurrah!

This is because a hash is a one-way function. It's mathematically quick and easy to convert from a password to a hash, but it's unfeasibly complicated to work it backwards. It's a bit like how if I ask you to square a large number, that's a pretty easy thing to do in your head (or with a bit of paper), right? But if I ask you what the square root of an extremely large number is... that's a lot harder. Some mathematical operations are easy in one direction, but hard in the other. That's the black magic that hashing depends upon. (In reality, it's not square roots, but it's a good analogy.)

This works no matter how the hashes is stored. Your hash is stored in the source code, but on a bigger system with lots of users the hashes would probably be stored in a database alongside their corresponding usernames. Same diff.

Why your passwords should be hashed; reason 2

The second way that hashing protects you is (done properly) it limits the feasibility of precalculated dictionaries and rainbow tables. Imagine this: if 'pass' always hashed to, say, '4528e6a7bb9341c36c425faf40ef32c3', and 'hunter2' always hashed to '6a0f0731d84afa4082031e3a72354991' (this is the case if you use a hashing algorithm called MD5, which - among its other problems - is not suitable for passwords)... then I, a Bad Guy, could pre-make a dictionary of all the most-common passwords and what their hashes are. Then, when I break into your server and steal your hash, I can just compare it to my pre-calculated dictionary to find what original password you chose that turned-into that hash. And then I'm into your email and online banking again, boo!

This (and a much more-complex approach called rainbow tables, which relate to breaking down each step of a multi-step hashing algorithm) kind of attack gets mitigated by something called salting. When you salt a password hash, you season it with a little extra random string before you hash it. That way, if the password 'pass' gets hashed two times in the same database of users, it looks different. The only way an attacker knows that those two people have the same password is to break each and every one of them, one at a time, which in turn is made harder because none of their pre-calculated dictionaries (which tend to be based on common passwords, words, words separated by numbers or symbols, etc., random strings up to a particular length, and so on) have that particular salt on the start.

But you don't actually need to know any of that...

Thankfully, if you use a modern programming language "properly", you never have to think about any of the above. For PHP, that means to just remember:

- don't store passwords, turn them into hashes with $the_hash = password_hash($the_password, PASSWORD_DEFAULT)
- when checking if a password is correct, don't use ==, use password_verify($the_password, $password_hash))

(Incidentally: password_verify() protects you in another way, from timing attacks: in some circumstances, an attacker can derive how close their guess is to the actual password by timing how long it takes the server to compare the hashes, because if it only has to check the first two characters of the hash to know if it's wrong that means it's more-wrong than if the server has to check 75% of the hash. password_verify() always checks every character in a hash, even if the first one was wrong, to mitigate this attack, but using == does not! The more you know!)
Logged

https://danq.me/_q26t/badges/dan-q-88x31-lighter.gif https://danq.me/_q26t/badges/dan-q-88x31-peekaboo-scroller.gif https://beige-buttons.danq.dev/beige-buttons-88x31.gif https://embed-html.danq.dev/embed-html-88x31.gif

Artifact Swap: I met Dan Q on Melonland!PolyamorousBouncy Egg!Joined 2025!Lurby
clownvomitz
Casual Poster ⚓︎
*
View Profile WWW


they/he/it
⛺︎ My Room
StatusCafe: clownvomitz
iMood: clownvomitz
RSS: RSS

Guild Memberships:
Artifacts:
Joined 2026!
« Reply #7 on: May 10, 2026 @699.85 » Embed

Wow awesome! Thank you so much for all of this information, if you couldn’t tell I’m completely new to all of this and I appreciate how in depth your replies have been!! I’ll definitely look into hashing my passwords for my site for future use, makes a ton of sense!
Logged

https://file.garden/ZpyoPBriBHjSP-h5/nb.gifvhttps://file.garden/ZpyoPBriBHjSP-h5/hb.gifv
https://adriansblinkiecollection.neocities.org/e65.gifhttps://adriansblinkiecollection.neocities.org/e48.gif
"sunrise, parabellum"

Artifact Swap: Batman Spiffo
Pages: [1] Print Embed 
« previous next »
 

Melonking.Net © Always and ever was! SMF 2.0.19 | SMF © 2021 | Privacy Notice | ~ Send Feedback ~ Forum Guide | Rules | RSS | WAP | Mobile


MelonLand Badges and Other Melon Sites!

MelonLand Project! Visit the MelonLand Forum! Support the Forum
Visit Melonking.Net! Visit the Gif Gallery! Pixel Sea TamaNOTchi

MelonLand Nav

@000

Want to Login or Join ?

Minecraft: Online
Join: craft.melonking.net