web-dev-qa-db-fra.com

Se connecter uniquement si l'utilisateur est actif avec Laravel

Je travaille actuellement sur mon application Laravel et, pour éviter les spams, j'ai décidé que seuls les utilisateurs actifs pouvaient se connecter . J'utilise actuellement le système de connexion de Laravel, comme dans le didacticiel du site officiel de Laravel, voici mon formulaire:

<form class="form-horizontal" role="form" method="POST" action="{{ url('/auth/login') }}">

Cela fonctionne parfaitement, mais j'aimerais vérifier si l'utilisateur est actif, sinon, il serait redirigé vers la page d'activation, sinon il se connecterait .. Est-ce qu'il existe un moyen simple de le faire ou suis-je obligé de le faire un nouveau contrôleur, des routes et plus de vérifications? Je vous remercie.

Edit: J'ai oublié de mentionner que j'ai une colonne 'active' dans ma base de données.

17
Micael Sousa

Laravel 5.4/5.5

Remplacez la fonction login() par défaut en plaçant cette fonction dans votre LoginController:

public function login(\Illuminate\Http\Request $request) {
    $this->validateLogin($request);

    // If the class is using the ThrottlesLogins trait, we can automatically throttle
    // the login attempts for this application. We'll key this by the username and
    // the IP address of the client making these requests into this application.
    if ($this->hasTooManyLoginAttempts($request)) {
        $this->fireLockoutEvent($request);
        return $this->sendLockoutResponse($request);
    }

    // This section is the only change
    if ($this->guard()->validate($this->credentials($request))) {
        $user = $this->guard()->getLastAttempted();

        // Make sure the user is active
        if ($user->active && $this->attemptLogin($request)) {
            // Send the normal successful login response
            return $this->sendLoginResponse($request);
        } else {
            // Increment the failed login attempts and redirect back to the
            // login form with an error message.
            $this->incrementLoginAttempts($request);
            return redirect()
                ->back()
                ->withInput($request->only($this->username(), 'remember'))
                ->withErrors(['active' => 'You must be active to login.']);
        }
    }

    // If the login attempt was unsuccessful we will increment the number of attempts
    // to login and redirect the user back to the login form. Of course, when this
    // user surpasses their maximum number of attempts they will get locked out.
    $this->incrementLoginAttempts($request);

    return $this->sendFailedLoginResponse($request);
}

Il est recommandé de remplacer la méthode login() de cette manière par rapport à la plupart des autres réponses à cette question, car elle vous permet de continuer à utiliser la plupart des fonctionnalités d’authentification les plus avancées de Laravel 5.4+ telles que la limitation de connexion, plusieurs pilotes/fournisseurs de protection d’authentification, etc. tout en vous permettant de définir un message d'erreur personnalisé.


Laravel 5.3

Modifiez ou remplacez votre fonction postLogin() dans votre AuthController pour ressembler à ceci:

public function postLogin(Request $request)
{
    $this->validate($request, [
        'email' => 'required|email', 'password' => 'required',
    ]);

    $credentials = $this->getCredentials($request);

    // This section is the only change
    if (Auth::validate($credentials)) {
        $user = Auth::getLastAttempted();
        if ($user->active) {
            Auth::login($user, $request->has('remember'));
            return redirect()->intended($this->redirectPath());
        } else {
            return redirect($this->loginPath()) // Change this to redirect elsewhere
                ->withInput($request->only('email', 'remember'))
                ->withErrors([
                    'active' => 'You must be active to login.'
                ]);
        }
    }

    return redirect($this->loginPath())
        ->withInput($request->only('email', 'remember'))
        ->withErrors([
            'email' => $this->getFailedLoginMessage(),
        ]);

}

Ce code redirige vers la page de connexion avec un message d'erreur indiquant que l'utilisateur est inactif. Si vous souhaitez rediriger vers une page d'authentification, vous devez modifier la ligne marquée du commentaire Change this to redirect elsewhere.

46
BrokenBinary

Dans Laravel 5.4, ouvrez Auth/LoginController.php

et ajoutez cette fonction:

/**
     * Get the needed authorization credentials from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function credentials(\Illuminate\Http\Request $request)
    {
        //return $request->only($this->username(), 'password');
        return ['email' => $request->{$this->username()}, 'password' => $request->password, 'status' => 1];
    }

Et vous avez terminé ..!

36
Raja Amer Khan

Cette solution est basée sur l’idée de Can Celik et a été testée avec Laravel 5.3.

protected function validateLogin(Request $request)
{
    $this->validate($request, [
        $this->username() => 'required|exists:users,' . $this->username() . ',active,1',
        'password' => 'required',
    ]);
}

Les deux derniers paramètres séparés par des virgules (active,1) agissent comme une clause WHERE (WHERE active = '1') et peuvent également être écrits comme suit:

protected function validateLogin(Request $request)
{
    $this->validate($request, [
        $this->username() => [
            'required',
            Rule::exists('users')->where(function ($query) {
                $query->where('active', 1);
            }),
        ],
        'password' => 'required'
    ]);
}

Normalement, la méthode de validation vérifie uniquement si les champs email et mot de passe sont remplis. Avec la modification ci-dessus, nous exigeons qu'une adresse électronique donnée soit trouvée dans une ligne de base de données avec la valeur active définie sur 1.

UPDATE (testé avec Laravel 5.5):

Vous pouvez également personnaliser le message:

protected function validateLogin(Request $request)
{
    $this->validate($request, [
        $this->username() => 'required|exists:users,' . $this->username() . ',active,1',
        'password' => 'required',
    ], [
        $this->username() . '.exists' => 'The selected email is invalid or the account has been disabled.'
    ]);
}

Notez que le message ci-dessus apparaîtra à la fois lorsqu'une adresse électronique donnée n'existe pas ou lorsque le compte est désactivé.

13
Mateusz

dans AuthController, remplacez la méthode getCredentials comme ceci:

protected function getCredentials(Request $request) {

        $request['active'] = TRUE;
        return $request->only($this->loginUsername(), 'password', 'active');
}

assurez-vous que la colonne est active sur la table utilisateur ...

6
pls13

Vous n'avez pas à remplacer toute la fonction. Vous pouvez simplement changer le validateur dans AuthController pour obtenir cette validation en ajoutant la validation "existe: table, colonne".

Supposons que vous ayez une table d'utilisateurs avec email, mot de passe et champs actifs.

protected function validator(array $data)
{
    return Validator::make($data, [
        'email' => 'required|email|max:255|exists:users,email,active,1',
        'password' => 'required|confirmed'
    ]);
}

ou si vous utilisez des suppressions douces, cela devrait également fonctionner.

'email' => 'existe: utilisateurs, email, delete_at, NULL'

Vous pouvez également consulter la règle de validation à ce lien http://laravel.com/docs/5.1/validation#rule-exists

3
Can Celik

Si quelqu'un utilise une requête ajax lors de la connexion et souhaite créer un message personnalisé, voici comment j'ai réalisé cela dans login controller :

fonction login ()

  // This section is the only change
    if ($this->guard()->validate($this->credentials($request))) {
        $user = $this->guard()->getLastAttempted();

        // Make sure the user is active
        if ($user->status == 1 && $this->attemptLogin($request)) {
            // Send the normal successful login response
            return $this->sendLoginResponse($request);
        } else {
            // Increment the failed login attempts and redirect back to the
            // login form with an error message.
            $this->incrementLoginAttempts($request);
            return $this->sendFailedLoginResponse($request, true);
        }
    }

Et autres fonctions

 public function sendLoginResponse(Request $request)
{
    $redirectTo = false;
    if ($request->headers->get('referer') == env('APP_URL') . '/' || $request->headers->get('referer') == env('APP_URL') . '/login') {
        $redirectTo = $this->redirectPath();
    }

    if ($request->expectsJson()) {
        return response()->json(['status' => true, 'user' => auth()->user(), 'redirectTo' => $redirectTo, 'fragments' => [
            '#main-nav' => view('includes.nav')->render()
        ]]);
    } else {
        return redirect($redirectTo);
    }
}

public function sendFailedLoginResponse(Request $request, $user_not_active = fasle)
{
    if ($user_not_active) {
        return response()->json(['status' => false, 'email' => 'Your account is not active.']);
    }
    return response()->json(['status' => false, 'email' => 'Incorrect login credentials.']);
}
1
Piotr Jankiewicz

Je vérifie que l'utilisateur est activé par la fonction sendLoginResponse de remplacement dans LoginController

protected function sendLoginResponse(Request $request)
{
    if($this->guard()->user()->active == 0){
        $this->guard()->logout();
        return redirect()->back()
            ->withInput($request->only($this->username(), 'remember'))
            ->withErrors(['active' => 'User in not activated.']);
    }

    $request->session()->regenerate();

    $this->clearLoginAttempts($request);

    return $this->authenticated($request, $this->guard()->user())
            ?: redirect()->intended($this->redirectPath());
}
1
Mohsen

Si quelqu'un est venu ici pour rechercher des informations sur Laravel 5.4/5.5, ce qui permet de personnaliser le message uniquement pour ce scénario (pas un message combiné), voici la réponse à partir de https://laracasts.com/discuss/ canaux/laravel/user-account-status

Remplacez la méthode 'authentifiée' dans votre fichier 'app/Http/Controllers/Auth/LoginController.php`:

/**
 * The user has been authenticated.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  mixed  $user
 * @return mixed
 */
protected function authenticated(Request $request, $user)
{
    if ($user->status_id == 2) { // or whatever status column name and value indicates a blocked user

        $message = 'Some message about status';

        // Log the user out.
        $this->logout($request);

        // Return them to the log in form.
        return redirect()->back()
            ->withInput($request->only($this->username(), 'remember'))
            ->withErrors([
                // This is where we are providing the error message.
                $this->username() => $message,
            ]);
    }
}
0
daprezjer

Merci @Can_Celik

c'est ainsi que j'ai pu résoudre mon problème parce que j'utilisais json response avec jQuery.

/**
     * Validate the user login request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return void
     */
    protected function validateLogin(Request $request)
    {
        $this->validate($request, [
            'email' => 'required|email|exists:users_table,email,account_status_colunm,active_value',
            'password' => 'required',
        ]);
    }

puis dans le fichier validation.php ajoutez ceci à vos chaînes de validation personnalisées

...
'email' => [
        'exists' => 'Account has been disabled. Contact our team.'
    ],

c'est à peu près tout ... fonctionne bien ...

0
The Dead Guy