web-dev-qa-db-fra.com

PHP classe d'utilisateur (connexion / déconnexion / inscription)

J'ai commencé à expérimenter avec la création de classes, et j'ai commencé par convertir mon enregistrement/connexion utilisateur en une seule classe. Je voulais arrêter et demander des commentaires avant d'aller trop loin.

class UserService
{
    private $_email;
    private $_password;

    public function login($email, $password)
    {
        $this->_email = mysql_real_escape_string($email);
        $this->_password = mysql_real_escape_string($password);

        $user_id = $this->_checkCredentials();
        if($user_id){
            $_SESSION['user_id'] = $user_id;
            return $user_id;
        }
        return false;
    }

    protected function _checkCredentials()
    {
        $query = "SELECT *
                    FROM users
                    WHERE email = '$this->_email'";
        $result = mysql_query($query);
        if(!empty($result)){
            $user = mysql_fetch_assoc($result);
            $submitted_pass = sha1($user['salt'] . $this->_password);
            if($submitted_pass == $user['password']){
                return $user['id'];
            }
        }
        return false;
    }   
}

L'une des questions que j'ai sur ma classe est la suivante: dois-je la construire comme ceci:

$User = new UserService();
$User->login($_POST['email'], $_POST['password']);

Où la méthode de connexion appelle automatiquement la méthode _checkCredentials. Ou doit-il être construit comme:

$User = new UserService();
$UserId = $User->checkCredentials($_POST['email'], $_POST['password']);
$User->login($UserId);

En dehors de cela, j'adore quelques conseils sur la façon de restructurer cela et veuillez signaler tout ce que je fais mal!

merci les gars

26
Nouman

J'ai déjà beaucoup dit cela sur stackoverflow, mais ce que je pense que vous faites mal, c'est que vous à nouveau essayez de créer un système de connexion (même Jeff Atwood d'accord avec moi à ce sujet) qui va probablement être dangereux. Juste pour nommer quelques choses qui pourraient se tromper :

  • Vous ne faites pas d'authentification sur une connexion sécurisée (https), ce qui signifie que votre nom d'utilisateur/mot de passe peut être reniflé du fil.
  • Il pourrait y avoir un trou XSS.
  • les mots de passe ne sont pas stockés en sécurité dans la base de données en raison d'une utilisation incorrecte du sel. Vous n'êtes pas un expert en sécurité, donc je ne pense pas que vous devriez même stocker de telles informations sensibles dans votre base de données de toute façon!
  • Il a un CSRF - trou.

Ensuite, il y a la gêne que nous devons encore créer un autre compte sur votre serveur. Vous pouvez et devez éviter ces tracas en utilisant l'une des alternatives disponibles gratuitement qui ont été testées par des experts pour les failles de sécurité:

  • openid => Lightopenid est une bibliothèque vraiment facile à utiliser/intégrer. Même stackoverflow/jeff atwood l'utilise car il sait qu'il est difficile d'obtenir correctement le système de connexion. Même si vous êtes un expert en sécurité.
  • google friend connect.
  • facebook se connecte.
  • Connexion unique sur Twitter.

Alors, protégez-vous le temps de concevoir à nouveau un autre système de connexion et utilisez plutôt la bibliothèque Lightopenid vraiment simple et laissez les utilisateurs se connecter avec leur compte Google. L'extrait ci-dessous est le seul code dont vous avez besoin pour le faire fonctionner:

<?php
# Logging in with Google accounts requires setting special identity, so this example shows how to do it.
require 'openid.php';
try {
    $openid = new LightOpenID;
    if(!$openid->mode) {
        if(isset($_GET['login'])) {
            $openid->identity = 'https://www.google.com/accounts/o8/id';
            header('Location: ' . $openid->authUrl());
        }
?>
<form action="?login" method="post">
    <button>Login with Google</button>
</form>
<?php
    } elseif($openid->mode == 'cancel') {
        echo 'User has canceled authentication!';
    } else {
        echo 'User ' . ($openid->validate() ? $openid->identity . ' has ' : 'has not ') . 'logged in.';
    }
} catch(ErrorException $e) {
    echo $e->getMessage();
}
14
Alfred

Cela dépend de votre conception et de la notion d'une solution plus simple, et de la façon dont vous voulez organiser votre code et le garder plus simple, plus petit et le rendre maintenable en même temps.

Demandez-vous pourquoi vous appelez checkCredentials puis appelez login et peut-être une autre méthode. Avez-vous une bonne raison de le faire, est-ce une bonne conception, qu'est-ce que je veux réaliser avec cela.

Appeler simplement login et effectuer chaque opération de connexion est beaucoup plus simple et élégant. Lui donner un autre nom en le faisant est beaucoup plus compréhensible et aussi plus maintenable.

Si vous me demandez, j'utiliserais un constructeur.

1
Secko

La réponse dépend vraiment d'autres considérations d'architecture, par exemple si la méthode checkCredentials () doit être disponible en dehors de la portée de classe pour d'autres éléments du système. Si son seul but est d'être appelé par la méthode login (), envisagez de combiner les deux en une seule méthode.

Une autre recommandation que je pourrais faire est d'utiliser des verbes dans les méthodes de nommage, ce qui signifie que la "connexion" peut être trop générale pour comprendre ses effets à première vue.

0
Dennis Kreminsky