php 仅当用户使用 Laravel 处于活动状态时才登录

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31015606/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 22:11:56  来源:igfitidea点击:

Login only if user is active using Laravel

phplaravellaravel-5loginaccount

提问by Micael Sousa

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:

我目前正在开发我的 Laravel 应用程序,为了防止垃圾邮件,我决定只有活跃用户才能登录。我目前正在使用 Laravel 的登录系统,就像在 Laravel 的官网教程中一样,这是我的表单操作:

<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.

编辑:忘记提及我的数据库中有一个“活动”列。

回答by BrokenBinary

Laravel 5.4 / 5.5

Laravel 5.4 / 5.5

Override the default login()function by placing this function in your LoginController:

覆盖默认login()通过将该功能在你的函数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);
}

Overriding the login()method in this way is recommended over many of the other answers on this question because it allows you to still use many of the more advanced authentication functionality of Laravel 5.4+ such as login throttling, multiple authentication guard drivers/providers, etc. while still allowing you to set a custom error message.

login()建议以这种方式覆盖此问题的许多其他答案,因为它允许您仍然使用 Laravel 5.4+ 的许多更高级的身份验证功能,例如登录限制、多个身份验证保护驱动程序/提供程序等。仍然允许您设置自定义错误消息。



Laravel 5.3

Laravel 5.3

Change or override your postLogin()function in your AuthControllerto look like this:

更改或覆盖您的postLogin()函数,AuthController如下所示:

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(),
        ]);

}

This code redirects back to the login page with an error message about the user being inactive. If you want to redirect to an authentication page you would change the line I marked with the comment Change this to redirect elsewhere.

此代码重定向回登录页面,并显示有关用户处于非活动状态的错误消息。如果您想重定向到身份验证页面,您可以更改我用注释标记的行Change this to redirect elsewhere

回答by Raja Amer Khan

In Laravel 5.4 open Auth/LoginController.php

在 Laravel 5.4 打开 Auth/LoginController.php

and add this function:

并添加此功能:

/**
     * 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];
    }

And you are done..!

你完成了..!

回答by Mateusz

Paste the following method to your LoginController.

将以下方法粘贴到您的LoginController.

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

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

最后两个逗号分隔的参数 ( active,1) 充当 WHERE 子句 ( WHERE active = '1'),也可以这样写:

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

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 activevalue set to 1.

通常,验证方法仅检查是否填写了电子邮件和密码字段。通过上面的修改,我们要求在active值设置为 1的 DB 行中找到给定的电子邮件地址。

You can also customize the message:

您还可以自定义消息:

protected function validateLogin(Request $request)
{
    $this->validate($request, [
        $this->username() => 'exists:users,' . $this->username() . ',active,1',
        'password' => 'required|string',
    ], [
        $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.

请注意,当给定的电子邮件地址不存在或帐户被禁用时,将显示上述消息。

回答by pls13

in AuthController override method getCredentials like this:

在 AuthController 覆盖方法 getCredentials 中,如下所示:

protected function getCredentials(Request $request) {

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

make sure you have the column active on user table...

确保您在用户表上的列处于活动状态...

回答by Can Celik

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.

您不必覆盖整个函数。您只需更改 AuthController 中的 Validator 即可实现添加“exists:table,column”验证。

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

这是验证器函数应该在 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

您还可以在此链接http://laravel.com/docs/5.1/validation#rule-exists查看验证规则

回答by Piotr Jankiewicz

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

如果有人在登录时使用 ajax 请求并想要自定义消息,这是我在登录控制器中实现的方法:

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.']);
}

回答by thiago tanaka

Laravel 5.8 tested. Put this code in your LoginController.php and be happy.

Laravel 5.8 测试。将此代码放在您的 LoginController.php 中并高兴。

public function login(Request $request)
{
    $user = User::where('username',$request->username)->first();
    if( $user && !$user->active){
        return redirect()->back()->with('error','the user has been desactivated');
    }

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

    if ($this->attemptLogin($request)) {
        return $this->sendLoginResponse($request);
    }

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

回答by PatricNox

Most logical, and clean, is to handle this within the validateLogin method.

最合乎逻辑且干净的方法是在 validateLogin 方法中处理此问题。

LoginController.php(Laravel 6.x)

LoginController.php (Laravel 6.x)

/**
 * Validate the user login request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return void
 *
 * @throws \Illuminate\Validation\ValidationException
 */
protected function validateLogin(Request $request)
{
    // Get the user details from database and check if email is verified.
    $user = User::where('username', '=', $request->input($this->username()))->first();
    if ($user->email_verified_at == NULL) {
        throw ValidationException::withMessages([$this->username() => __('auth.failed_login_missing_email_verification')]);
    }

    // Email is verified, validate input.
    return $request->validate([
        $this->username() => 'required|string',
        'password' => 'required|string',
    ]);
}

回答by basak

Laravel 6.6 tested.Overwrite validateLoginin your LoginController.php

Laravel 6.6 测试。validateLogin在您的 LoginController.php 中覆盖

use Illuminate\Http\Request;
use App\User;
use Illuminate\Validation\ValidationException;

......

......

/**
 * Validate the user login request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return void
 *
 * @throws \Illuminate\Validation\ValidationException
 */
protected function validateLogin(Request $request)
{
    // Get the user details from database and check if user is exist and active.
    $user = User::where('email',$request->email)->first();
    if( $user && !$user->activation){
        throw ValidationException::withMessages([$this->username() => __('User has been desactivated.')]);
    }

    // Then, validate input.
    return $request->validate([
        $this->username() => 'required|string',
        'password' => 'required|string',
    ]);
}

回答by daprezjer

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

如果有人来这里寻找有关 Laravel 5.4/5.5 的信息,并且允许仅针对此场景的自定义消息(不是组合消息),这里是来自https://laracasts.com/discuss/channels/的答案laravel/用户帐户状态

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

覆盖您的“app/Http/Controllers/Auth/LoginController.php”文件中的“authenticated”方法:

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