Avatar billede riefart Seniormester
16. september 2021 - 14:20 Der er 8 kommentarer og
3 løsninger

Opdatering af alle poster

Jeg har en tabel i min MySql-database, hvor jeg bl.a. har gemt brugernes password, som ren tekst (ved godt at det var rimeligt usmart-OG det er også ændret for nye brugere).
Jeg har brug for at opdatere- og 'hash'e alle eksisterende usikre passwords på en gang.  Hvordan kan det lade sig gøre?

Jeg bruger følgende syntaks til insert:
$email=$_POST["email"];
$password=$_POST["password"];
$hash=password_hash($password, PASSWORD_DEFAULT);
if($stmt=$mysqli->prepare("insert into `brugere` (......`email`, `hash`, ......  VALUES(?,?,?,?,)"))  {
$stmt->bind_param('isssisis',.... $email, $hash, ....);
$stmt->execute();
$stmt->close();
Men er ganske usikker på hvordan jeg kan lave den ønskede update.
Avatar billede arne_v Ekspert
16. september 2021 - 16:56 #1
Du bliver nok nød til at lave en SELECT som henter alle dem der skal opdateres og lave en UPDATE for hver.

UPDATE kan godt opdatere mange rækker, men du skal bruge en PHP funktion ikke en SQL funktion til at generere de nye værdier, så derfor flee UPDATE.
Avatar billede riefart Seniormester
16. september 2021 - 18:56 #2
Ja, det regnede jeg også med, da de jo skal behandles hver for sig i forhold til hash'en.
Jeg er bare temmelig usikker på syntaksen. Har du lyst til at smide et forslag, Arne?
Avatar billede arne_v Ekspert
16. september 2021 - 20:27 #3
Demo:


<?php
function get_connection() {
    $con = new mysqli('localhost', 'root', '', 'Test');
    if(mysqli_connect_errno()) {
        die(mysqli_connect_error());
    }
    return $con;
}

function insert($con, $stmt, $un, $pw) {
    $stmt->bind_param('ss', $un, $pw);   
    $stmt->execute() or die(mysqli_error($con));
}

function setup() {
    $con = get_connection();
    $con->query('CREATE TABLE unpw (un VARCHAR(32), pw VARCHAR(256), PRIMARY KEY(un))') or die(mysqli_error($con));
    $stmt = $con->prepare('INSERT INTO unpw VALUES(?,?)') or die(mysqli_error($con));
    insert($con, $stmt, 'A', 'Not updated');
    insert($con, $stmt, 'B', 'Not updated');
    insert($con, $stmt, 'C', 'Not updated');
    insert($con, $stmt, 'D', 'Updated');
    $stmt->close();
    $con->close();
}

function dump() {
    $con = get_connection();
    $rs = $con->query('SELECT un,pw FROM unpw') or die(mysqli_error($con));
    while($row = $rs->fetch_array(MYSQLI_ASSOC)) {
        $un = $row['un'];
        $pw = $row['pw'];
        echo "$un $pw\r\n";
    }
    $con->close();
}

function teardown() {
    $con = get_connection();
    $con->query('DROP TABLE unpw') or die(mysqli_error($con));
    $con->close();
}

function superhash($pw) {
    return 'Updated';
}

function update() {
    $selcon = get_connection();
    $updcon = get_connection();
    $selstmt = $selcon->prepare('SELECT un,pw FROM unpw WHERE pw = ?') or die(mysqli_error($selcon));
    $updstmt = $updcon->prepare('UPDATE unpw SET pw = ? WHERE un = ?') or die(mysqli_error($updcon));
    $targetpw = 'Not updated';
    $selstmt->bind_param('s', $targetpw);
    $selstmt->execute() or die(mysqli_error($selcon));
    $rs = $selstmt->get_result();
    while($row = $rs->fetch_array(MYSQLI_ASSOC)) {
        $un = $row['un'];
        $pw = $row['pw'];
        $newpw = superhash($pw);
        $updstmt->bind_param('ss', $newpw, $un);
        $updstmt->execute() or die(mysqli_error($updcon));
    }
    $updstmt->close();
    $selstmt->close();
    $updcon->close();
    $selcon->close();
}

setup();
dump();
update();
dump();
teardown();

?>
Avatar billede arne_v Ekspert
16. september 2021 - 20:28 #4
Det er med vilje at jeg bruger 2 connections og 2 statements i update!
Avatar billede riefart Seniormester
16. september 2021 - 22:31 #5
Tak for demo'en, Arne. Det ser meget spændende - og lidt kompliceret ud. Glæder mig til at nærlæse og afprøve i morgen.
Avatar billede riefart Seniormester
16. september 2021 - 22:56 #6
Men tænker lige: bliver der noget at se, hvis function teardown() kører til slut?
Den sletter vel tabellen, eller hvad?
Avatar billede arne_v Ekspert
17. september 2021 - 03:22 #7
Du skal kun kigge paa funktionen update.

setup og teardown er for at jeg kan teste med nogle data.

dump er for at kunne verificere at det virker.

Og de specifikke SQL saetninger i update skal ogssa justeres til din tabel struktur og din konvention for password.

Og superhash skal ersttates af en rigtig hash.

Kig paa update og:
- 2 connections
- 2 statements
- SELECT som finder alle dem der skal opdateres
- UPDATE som opdatyerer en der skal opdateres
Avatar billede riefart Seniormester
18. september 2021 - 11:08 #8
Hej Arne. Det giver mening.
Jeg er dog lidt usikker på hvordan jeg skal angive:  $targetpw
$targetpw = 'Not updated';
$selstmt->bind_param('s', $targetpw);

kan du give et vink her?
Avatar billede riefart Seniormester
18. september 2021 - 15:28 #9
Jeg slette de to ovenstående linier i scriptet, og så virkede det, som det skulle.
Tak for hjælpen.
Avatar billede arne_v Ekspert
18. september 2021 - 20:09 #10
$selstmt = $selcon->prepare('SELECT un,pw FROM unpw WHERE pw = ?') or die(mysqli_error($selcon));
...
    $targetpw = 'Not updated';
    $selstmt->bind_param('s', $targetpw);

var for at udvaelge dem som har behov for opdatering.

Du skulle sikkert have en anden logik. Test  på længden af password eller test på om salt forskellige fra nul.
Avatar billede arne_v Ekspert
20. september 2021 - 02:05 #11
Ideen med en SELECT og en while løkke med en UPDATE er jo nærmest selvindlysende.

Tricket er de 2 connections & statements.

De fleste databaser herunder MySQL kan ikke håndtere at man udfører en UPDATE på connection mens men stadig er ved at hente data fra en SELECT.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester