Login only if user is active using Laravel

2019-01-13 14:14发布

I'm currently working on my Laravel app and to prevent spam I decided that only active users are able to login. I'm currently using Laravel's login system just like in Laravel's official website tutorial, here's my form action:

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

This works completely fine, however I'd like to check the user's active, if not active it would be redirected to the activation page, otherwise it would login. Is there a simple way to do this or am I obligated to make a new controller, routes and more verifications? Thank you.

Edit: Forgot to mention that I have a 'active' column in my database.

9条回答
男人必须洒脱
2楼-- · 2019-01-13 14:21

This solution is based on Can Celik's idea and was tested with Laravel 5.3.

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

The last two comma-separated parameters (active,1) act as a WHERE clause (WHERE active = '1') and can be alternatively written this way:

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

Normally, the validation method only checks if email and password fields are filled out. With the modification above we require that a given email address is found in a DB row with active value set to 1.

UPDATE (tested with Laravel 5.5):

You can also customize the 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.'
    ]);
}

Note that the above message will be shown both when a given email address doesn't exist or when the account is disabled.

查看更多
\"骚年 ilove
3楼-- · 2019-01-13 14:22

If someone uses ajax request on login and wants to have custom message, here is how I achieved this in login controller:

login() function

  // 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);
        }
    }

And other functions

 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.']);
}
查看更多
ゆ 、 Hurt°
4楼-- · 2019-01-13 14:23

You don't have to override the whole function. You can just change the Validator in AuthController to achieve that adding "exists:table,column" validation.

Let's assume that you have a users table with email,password and active fields.

'email' => 'exists:users,email,active,1'

Here is the validotor function should look like in AuthController.php

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

or if you are using soft deletes this should work too.

'email' => 'exists:users,email,deleted_at,NULL'

You can also check out the validation rule at this link http://laravel.com/docs/5.1/validation#rule-exists

查看更多
Emotional °昔
5楼-- · 2019-01-13 14:23

Thanks @Can_Celik

this was how I was able to solve my issue becos i was using json response with 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',
        ]);
    }

then in the validation.php file add this to your Custom Validation strings

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

that's about all...works fine ...

查看更多
啃猪蹄的小仙女
6楼-- · 2019-01-13 14:24

I check user is actived by overwrite sendLoginResponse function in 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());
}
查看更多
做个烂人
7楼-- · 2019-01-13 14:32

In case anyone is came here looking for information on Laravel 5.4/5.5, and that allows for a custom message just for this scenario (not a combined message) here's the answer for that from https://laracasts.com/discuss/channels/laravel/user-account-status

Override the 'authenticated' method within your'app/Http/Controllers/Auth/LoginController.php` file:

/**
 * 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,
            ]);
    }
}
查看更多
登录 后发表回答