Empfehlungen: Erweiterte Suche

Beim Update, das Passwordfeld in Ruhe lassen...

Daten auslesen, verarbeiten und den Views übergeben

Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon aioon » Fr 17. Jul 2009, 15:38

Hallo,

ich habe folgendes Problem:

Ich habe mit bake mir für die User das ganze MVC generieren lassen, nun habe ich immer das Problem, wenn ich users/edit/1 bearbeiten will, und z.B. nur den Namen ändern will, und es dann abspeichere, geht das passwort nicht mehr für diesen benutzer!

Password
[●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●]

So wie ich es sehe, wird das codierte Pass in das Feld geladen, und beim Edit, wird dieses codierte Pass wieder codiert...

Kann mir jemand bitte verraten, wie man dieses Problem umgehen kann, und wie muss man es eigentlich machen, wenn man jetzt doch sein Passwort ändern will?

Weil irgendwie bin ich verwirrt, ich denke dabei nur einen trigger...

Gruß
Alex
Dateianhänge
user_edit.jpg
user_edit.jpg (42.94 KiB) 562-mal betrachtet
aioon
 
Beiträge: 39
Registriert: So 12. Jul 2009, 18:14

Re: Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon Mathias » Fr 17. Jul 2009, 16:57

Hi,

ich habe das Passwortfeld umbenannt, so dass cake keinen Wert in inputfeld schreibt.

Im Model ist abr natürlich definiert, dass jeder User ein Passwort haben muss.

Zum Glück wird der Controller vor dem Model aufgerufen und du kannst dem Controller mitteilen, dass bestimmte Regeln im Model missachtet werden sollen.

Code: Alles auswählen
unset($this->User->validate['password']);


Du musst den Code natürlich deinem anpassen. Am besten du packst das Ganze in eine If-Else-Verzweigung. Wenn Passwort leer, dann unset. Wenn Passwort hat Wert, process...
cheers
Benutzeravatar
Mathias
 
Beiträge: 225
Registriert: Mi 4. Jun 2008, 22:30
Wohnort: Berlin
CakePHP-Version: 1.3.x
OS: OS X 10.6.x

Re: Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon aioon » Fr 17. Jul 2009, 17:01

ich habe das Passwortfeld umbenannt, so dass cake keinen Wert in inputfeld schreibt.

Im Model ist abr natürlich definiert, dass jeder User ein Passwort haben muss.


okay, dann könnte ich in ruhe die details bearbeiten, ohne das sich das passwort ständig ändert, wenn ich es jetzt umbennen in secretword,
und würde beim nächsten mal jetzt gerne das password ändern, würde da was eingeben, und absenden, wie soll man dann aber diese daten den speichern?
woher weiss den der controller, das gerade ein passwort übergeben worden ist alias secretword? den dieses muss jetzt codiert werden und abgespeichert!

außerdem, wird doch dieses secretsalt zeug für die generierung des passwortes mitbenutzt oder nicht?

ach, und wenn ich es so mache, indem ich das feld leer lasse:
Code: Alles auswählen
        echo $form->input('password', array('value' => ''));

bringt das auch nix, es setzt das password einfach auf _leer_

vll. muss ich noch erwähnen das ich den ACL component benutze!

bin wieder verwirrt :)

gruß
alex
aioon
 
Beiträge: 39
Registriert: So 12. Jul 2009, 18:14

Re: Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon aioon » Fr 17. Jul 2009, 19:23

habe jetzt die lösung:

controller -> edit:
Code: Alles auswählen
            // password change check
            if (!empty($this->data['User']['new_password'])) {
               
                $this->data['User']['password'] = $this->Auth->password($this->data['User']['new_password']);
           
            }

view -> edit
Code: Alles auswählen
echo $form->input('new_password', array('value' => '','label' => 'Passwort'));


gibt es da keine besser lösung? :)
aioon
 
Beiträge: 39
Registriert: So 12. Jul 2009, 18:14

Re: Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon Mathias » Fr 17. Jul 2009, 19:24

Hey Alex,

ich zeige einfach mal, wie ich das gemacht habe.

Auszug users_controller.php
Code: Alles auswählen
    function admin_edit() {
        $this->set('title', 'Edit User');
        if (!empty($this->data)) {
            if (empty($this->data['User']['new_password'])) { # Hat das Feld einen Wert?
                unset($this->User->validate['new_password']); # Nein. Ignoriere die Regel.
            } else {
                $this->data['User']['password'] = $this->Auth->password($this->data['User']['new_password']); # Ja. Verschlüssele den Wert und speicher ihn in der Passwortvariable des Users um später über save() in der Datenbank gespeichert zu werden.
            }
            $this->User->create();
            if ($this->User->save($this->data)) {
                $this->Session->setFlash(__('Preferences saved', true), 'admin_flash_success');
            } else {
                $this->Session->setFlash(__('Preferences could not be saved. Please check the error messages', true), 'admin_flash_failure');
            }
        } else {
            $this->data = $this->User->find('first', array('conditions' => array('User.id' => $this->Session->read('Auth.User.id')), 'recursive' => 0));
        }

    }


Auszug user.php (Model)
Code: Alles auswählen
    var $validate = array(
        'first_name' => array(
            array('rule' => 'alphaNumeric'),
            VALID_NOT_EMPTY
        ),
        'last_name' => array(
            array('rule' => 'alphaNumeric'),
            VALID_NOT_EMPTY
        ),
        'username' => array(
            array('rule' => 'alphaNumeric'),
            VALID_NOT_EMPTY,
            array('rule' => array('isUnique'))
        ),
        'email' => array(
            array('rule' => 'email'),
            VALID_NOT_EMPTY
        ),
        'new_password' => array(
            array('rule' => array('identicalFieldValues', 'password2')),
            array('rule' => array('minLength', '5'))
        )

    );
   
    function identicalFieldValues( $field=array(), $compare_field=null ) {
        foreach( $field as $key => $value ) {
            $v1 = $value;
            $v2 = $this->data[$this->name][ $compare_field ];              
            if($v1 !== $v2) {
                return FALSE;
            } else {
                continue;
            }
        }
        return TRUE;
    }


Auszug admin_edit.ctp
Code: Alles auswählen
<div class="form">
        <?php echo $form->create('User');?>
            <?php
                echo $form->error('first_name', array(
                                                0 => __('First name must contain letters or digits', true),
                                                1 => __('First name must not be empty', true)
                                                )
                );
                echo $form->error('last_name', array(
                                                0 => __('Last name must contain letters or digits', true),
                                                1 => __('Last name must not be empty', true)
                                                )
                );
                echo $form->error('username', array(
                                                0 => __('Username must contain letters or digits', true),
                                                1 => __('Username must not be empty', true),
                                                3 => __('Username already in use', true)
                                                )
                );
                echo $form->error('email', array(
                                                0 => __('E-Mail must be a valid address', true),
                                                1 => __('E-Mail must not be empty', true)
                                                )
                );
                echo $form->error('new_password', array(
                                                0 => __('Passwords do not match', true),
                                                1 => __('Password must have more than 5 characters', true)
                                                )
                );
                echo $form->input('id');
                echo $form->input('first_name', array('label' => __('First Name', true), 'error' => false));
                echo $form->input('last_name', array('label' => __('Last Name', true), 'error' => false));
                echo $form->input('username', array('label' => __('Username', true), 'error' => false));
                echo $form->input('email', array('label' => __('E-mail', true), 'error' => false));
                echo $form->input('new_password', array('type' => 'password', 'value' => '', 'label' => __('Password', true), 'error' => false));
                echo $form->input('password2', array('type' => 'password', 'value' => '', 'label' => __('Repeat Password', true), 'error' => false));
                echo $form->input('startpage_id', array('empty' => __('Standard behavior', true), 'label' => __('Startpage', true), 'error' => false));
            ?>
        <?php echo $form->end(__('Save', true));?>
        </div>
 



Im Controller frage ich ab, ob new_password einen Wert hat oder nicht. Hat es das nicht, so wird die Validierungsregel mit unset missachtet. Ist ein Wert vorhanden, so nehme ich diesen Wert, verschlüssele ihn mit Hilfe der Auth-Component und weise ihn $this->data['User']['password'] zu. Das ist die Zelle, in der das Passwort in der Datenbank gespeichert wird.

new_password und password2 sind lediglich Hilfsvariablen, die ich benutze um 1. ein leeres input-Field zu bekommen und 2. die Werte miteinander zu vergleichen.

Hoffe, ich konnte jetzt ein wenig Licht ins Dunkle bringen.
cheers
Benutzeravatar
Mathias
 
Beiträge: 225
Registriert: Mi 4. Jun 2008, 22:30
Wohnort: Berlin
CakePHP-Version: 1.3.x
OS: OS X 10.6.x

Re: Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon aioon » Fr 17. Jul 2009, 19:36

Hoa Mathias,

ich danke dir für die Mühe, anscheined ist das die gängiste Lösung dafür 8-)

bin ma gespannt, was auf mich noch alles zukommt, das mit dem passwort edit haben viele durchgemacht wie es aussieht :lol:

Vg
Alex
aioon
 
Beiträge: 39
Registriert: So 12. Jul 2009, 18:14

Re: Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon Luckie » Mo 26. Okt 2009, 12:28

Ich habe mittlerweile das selbe Problem. Es wundert mich etwas, dass Cake beim Backen das mit dem Passwort selber nicht geregelt bekommt.

Bei mir sieht das so aus wenn ich alle zugehörigen Dateien backe:
Code: Alles auswählen
function admin_form($form_action = 'add', $id = null) {
        if(!empty($id)){
            $user = $this->User->read(null, $id);
            $this->set('user', $user);
        }
        if (!empty($this->data)) {
        /* Email pruefen */
        if (($form_action == 'add') &amp;&amp; ($this->User->findByEmail($this->data['User']['email'])))
        {
            $this->Session->setFlash(__('Email address already exists', true), 'default', array(), 'info');
        }
        else
        {
            $this->User->create();
            if ($this->User->save($this->data)) { // hier wird gespeichert, aber das Passwortfeld hat schon den falschen Hash
                $this->Session->setFlash(__('The User has been saved', true), 'default', array(), 'info');
                if(!empty($id)){
                    $this->redirect(array('action' => 'view', $id));
                }else{
                    $this->redirect($this->referer());
                }
            } else {
                $this->Session->setFlash(__('The User could not be saved. Please, try again.', true), 'default', array(), 'error');
            }
        }
        }else{
            $this->data = array();
            $this->data['User'] = array();
            if(!empty($user)){
                $this->data = $user;
            }
            foreach($this->passedArgs as $fieldName => $value){
                $this->data['User'][$fieldName] = $value;
            }
        }
        $groups = $this->User->Group->generateTreeList(null, "{n}.Group.id", "{n}.Group.name", '--', 0);
        $this->set(compact('groups'));
        $form_url = '/' . $this->params['url']['url'];
        $this->set('form_url', $form_url);
        $this->set('form_action', $form_action);
    }


Erläuterung zu der Stelle mit dem Kommentar:
An dieser Stelle kommen die Daten aus dem Formular. Aber zu dem Zeitpunkt wurde das Passwort anscheinend schon zurückgesetzt, da der Hashwert nicht zum von mir vergebenen Passwort passt.

Meine Fragen sind jetzt:
Was passiert da?
Warum passiert es?
Und wie kann ich das alte Passwort erhalten, wenn es nicht geändert wurde?
Luckie
 
Beiträge: 115
Registriert: Fr 22. Mai 2009, 12:16
OS: Windows XP

Re: Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon Mathias » Mo 26. Okt 2009, 17:42

1. Frage: Bei der Benutzung von Auth wird das Standardpasswortfeld 'password' automatisch gehasht. Somit enthält $this->data schon das gehashte Passwort, wenn du mit dem Controller darauf zugreifst. Troubeshooting Auth Problems
2. Frage: Sicherheitsgründe? So sehr der Programmierer bin ich auch nicht, dass ich dir das erklären kann, sorry.
3. Frage: Antwort steht 2 Beiträge weiter oben.

Noch ein paar andere Anmerkungen: Sollte die E-Mail-Adresse nicht auf Model-Ebene überprüft werden? Sollte die Überprüfung fehlschlagen, kannst du die Fehlernachricht direkt unter das Eingabefeld packen.
Warum teilst du denn nicht add und edit in zwei verschiedene Funktionen auf? Dann brauchst du auch den Parameter $form_action übergeben und prüfen. Kann aber auch sein, dass ich irgendetwas in deiner Funktion übersehe, was das nötig macht.
Zuletzt geändert von Mathias am Di 27. Okt 2009, 10:01, insgesamt 1-mal geändert.
cheers
Benutzeravatar
Mathias
 
Beiträge: 225
Registriert: Mi 4. Jun 2008, 22:30
Wohnort: Berlin
CakePHP-Version: 1.3.x
OS: OS X 10.6.x

Re: Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon Luckie » Di 27. Okt 2009, 09:58

Zu der Aufteilung: Frag nicht mich, sondern frag die Entwickler von Cake. Einzig der Code für die E-Mail Überprüfung ist von mir, sonst wurde alles gebacken. Deswegen wundert es mich ja auch das Cake das mit dem Passwort nicht hinbekommt.

Der obige Code für die Lösung scheint mir irgendwie etwas aufwendig und so ganz verstanden habe ich ihn auch noch nicht. Hinzukommt, dass ich ihn vendors/shell/task einpflegen muss, da wir immer alles backen.
Luckie
 
Beiträge: 115
Registriert: Fr 22. Mai 2009, 12:16
OS: Windows XP

Re: Beim Update, das Passwordfeld in Ruhe lassen...

Beitragvon Mathias » Di 27. Okt 2009, 10:11

Wichtig ist, dass du das Eingabefeld nicht password nennst, wenn du ein nicht gehashtes Passwort willst. Nenn es new_password oder so.
In der Datenbank kann es weitehrin password heißen.

Hier ist der Codeschnipsel, der eigentlich relevant ist. Das ist eigentlich straight forward :geek:
Code: Alles auswählen
          if (empty($this->data['User']['new_password'])) {
                unset($this->User->validate['new_password']);
            } else {
                $this->data['User']['password'] = $this->Auth->password($this->data['User']['new_password']);
            }


Und zu der E-Mail-Überprüfung: Ich bin immer noch der Meinung, dass du die E-Mail im Model validieren solltest und nicht im Controller.
Probier doch mal im Model die E-Mail auf unique zu validieren.
Jetzt kam mir aber noch die Frage, warum du die Adresse nur bei add überprüfst. Danach könnte ich dann einfach eine schon verwendete E-Mail-Adresse eintragen? :shock:
cheers
Benutzeravatar
Mathias
 
Beiträge: 225
Registriert: Mi 4. Jun 2008, 22:30
Wohnort: Berlin
CakePHP-Version: 1.3.x
OS: OS X 10.6.x

Nächste

Zurück zu Controller

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste

cron