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

Php 仅当用户使用Laravel处于活动状态时登录,php,laravel,laravel-5,login,account,Php,Laravel,Laravel 5,Login,Account,我目前正在开发我的Laravel应用程序,为了防止垃圾邮件,我决定只有活跃用户才能登录。 我目前正在使用Laravel的登录系统,就像在Laravel的官方网站教程中一样,以下是我的表单操作: <form class="form-horizontal" role="form" method="POST" action="{{ url('/auth/login') }}"> 这工作完全好,但是我想检查用户的活动,如果不是活动的,它将被重定向到激活页面,否则它将登录。 有没有一个简

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

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

这工作完全好,但是我想检查用户的活动,如果不是活动的,它将被重定向到激活页面,否则它将登录。 有没有一个简单的方法可以做到这一点,或者我有义务做一个新的控制器,路由和更多的验证?多谢各位

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

Laravel 5.4/5.5 将默认的
login()
函数放置在
LoginController
中,以覆盖该函数:

公共函数登录(\illumb\Http\Request$Request){
$this->validateLogin($request);
//如果类正在使用ThrottlesLogins特性,我们可以自动进行节流
//此应用程序的登录尝试。我们将通过用户名和
//向此应用程序发出这些请求的客户端的IP地址。
如果($this->hastoomanyLogin尝试($request)){
$this->fireLockoutEvent($request);
返回$this->sendLockoutResponse($request);
}
//这一部分是唯一的变化
如果($this->guard()->validate($this->credentials($request))){
$user=$this->guard()->getlast();
//确保用户处于活动状态
如果($user->active&&$this->attemptLogin($request)){
//发送正常的成功登录响应
返回$this->sendLoginResponse($request);
}否则{
//增加失败的登录尝试并重定向回
//带有错误消息的登录表单。
$this->incrementLoginAttents($request);
返回重定向()
->back()
->withInput($request->only($this->username(),'memory'))
->withErrors(['active'=>“您必须处于活动状态才能登录。”]);
}
}
//如果登录尝试失败,我们将增加尝试次数
//登录并将用户重定向回登录表单。当然,当
//用户超过其最大尝试次数将被锁定。
$this->incrementLoginAttents($request);
返回$this->sendFailedLoginResponse($request);
}
与此问题的许多其他答案相比,建议以这种方式覆盖
login()
方法,因为它允许您仍然使用Laravel 5.4+的许多更高级的身份验证功能,例如登录限制、多个身份验证保护驱动程序/提供程序,等,同时仍允许您设置自定义错误消息


拉威尔5.3 更改或覆盖
AuthController
中的
postLogin()
函数,如下所示:

protected function getCredentials(Request $request) {

        $request['active'] = TRUE;
        return $request->only($this->loginUsername(), 'password', 'active');
}
class User extends Authenticatable {
...
/**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot() {
        parent::boot();

        static::addGlobalScope('scopeActive', function (Builder $builder) {
            $builder->where('active', 1);
        });
    }
...
公共函数后登录(请求$Request)
{
$this->validate$请求[
'email'=>'必填项| email'、'password'=>'必填项',
]);
$credentials=$this->getCredentials($request);
//这一部分是唯一的变化
if(Auth::validate($credentials)){
$user=Auth::getLastAttempted();
如果($user->active){
Auth::login($user,$request->has('memory');
return redirect()->designed($this->redirectPath());
}否则{
return redirect($this->loginPath())//将其更改为重定向到其他位置
->withInput($request->only('email','memory'))
->威瑟罗([
“活动”=>“您必须处于活动状态才能登录。”
]);
}
}
返回重定向($this->loginPath())
->withInput($request->only('email','memory'))
->威瑟罗([
'email'=>this->getFailedLoginMessage(),
]);
}

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

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

假设您有一个包含电子邮件、密码和活动字段的用户表

'email' => 'exists:users,email,active,1' 或者,如果您使用的是软删除,这应该也可以

'email' => 'exists:users,email,deleted_at,NULL' “电子邮件”=>“存在:用户、电子邮件、已删除位置、空”
您还可以在AuthController override method getCredentials中的此链接上签出验证规则,如下所示:

protected function getCredentials(Request $request) {

        $request['active'] = TRUE;
        return $request->only($this->loginUsername(), 'password', 'active');
}
class User extends Authenticatable {
...
/**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot() {
        parent::boot();

        static::addGlobalScope('scopeActive', function (Builder $builder) {
            $builder->where('active', 1);
        });
    }
...

确保用户表上的列处于活动状态…

将以下方法粘贴到
登录控制器中

protected function validateLogin(Request $request)
{
    $this->validate($request, [
        $this->username() => 'exists:users,' . $this->username() . ',active,1',
        'password' => 'required|string',
    ]);
}
最后两个逗号分隔的参数(
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'
    ]);
}
通常,验证方法仅检查是否填写了电子邮件和密码字段。通过上面的修改,我们要求在数据库行中找到一个给定的电子邮件地址,并且
active
值设置为1

您还可以自定义消息:

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

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

在Laravel 5.4中打开Auth/LoginController.php

protected function validator(array $data)
{
    return Validator::make($data, [
        'email' => 'required|email|max:255|exists:users,email,active,1',
        'password' => 'required|confirmed'
    ]);
}
use Illuminate\Http\Request;
use App\User;
use Illuminate\Validation\ValidationException;
并添加此功能:

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

你完了

如果有人来这里查找有关Laravel 5.4/5.5的信息,并且这允许仅针对此场景的自定义消息(而不是组合消息),以下是来自

覆盖“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,
            ]);
    }
}

我检查用户是否通过LoginController中的overwrite sendLoginResponse函数激活

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

如果有人在登录时使用ajax请求并想要定制消息,下面是我如何在登录控制器中实现这一点的
public function handle($request, Closure $next, ...$guards)
    {
        if(!$request->user()->active){
            // either abort with simple 403 access denied page
            // abort(403, "You don't have permissions to access this area");

            // OR force Logout and redirect back to the login page
            return redirect('login')->with($this->auth->logout());
        }

        $this->authenticate($request, $guards);
        return $next($request);
    }
public function __construct(Auth $auth)
    {
        $this->auth = $auth;
    }
class User extends Authenticatable {
...
/**
     * The "booting" method of the model.
     *
     * @return void
     */
    protected static function boot() {
        parent::boot();

        static::addGlobalScope('scopeActive', function (Builder $builder) {
            $builder->where('active', 1);
        });
    }
...
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);
}
/**
 * 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',
    ]);
}
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',
    ]);
}
<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable implements MustVerifyEmail
{
    use Notifiable;

    // ...
}
Auth::routes(['verify' => true]);
/**
 * Custom credentials to validate the status of user.
 */
public function credentials(Request $request)
{
    return [
        'email'     => $request->email,
        'password'  => $request->password,
        'is_active' => '1'
    ];
}
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
public function login(Request $request){        
    $this->validateLogin($request);

    if (method_exists($this, 'hasTooManyLoginAttempts') &&
        $this->hasTooManyLoginAttempts($request)) {
        $this->fireLockoutEvent($request);

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

    if($this->guard()->validate($this->credentials($request))) {
        // Check if user is active, else return error message
        if(Auth::attempt(['email' => $request->email, 'password' => $request->password, 'status' => 'A'])) {
            return redirect()->intended('dashboard');
        }  else {
            // This will return the message required as desired
            return $this->inactiveCredential($request);
        }
    } else {            
        $this->incrementLoginAttempts($request);
        return $this->sendFailedLoginResponse($request);
    }
}

// Error massage for inactive credential
private function inactiveCredential(Request $request){    
    throw ValidationException::withMessages([
        // auth.not-active can be added in resources/lang/en/auth.php
        $this->username() => [trans('auth.not-active')],
    ]);    
}
'not-active' => 'This account is already deleted. Contact administrator to revoke this account',
  protected function sendLoginResponse(Request $request) {
  $request->session()->regenerate();
  $this->clearLoginAttempts($request);
  if ($response = $this->authenticated($request, $this->guard()->user())) {
      return $response;
  }
  $user = $this->guard()->user();
  if($user->is_active) {
    return $request->wantsJson() ? new JsonResponse([], 204) : redirect()->intended($this->redirectPath());
  } else {
    $request->session()->flush();
    return redirect()->route('login')->with('error', 'This account is not activated. Please contact the administrator.');
  }    
}
class ForgotPasswordController extends Controller
{
    //...

    protected function credentials(Request $request)
    {
        // is_active field in user model must be true.
        $request->merge(['is_active' => true]);

        return $request->only('email', 'active');
    }
}
    public function login(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 (method_exists($this, 'hasTooManyLoginAttempts') &&
        $this->hasTooManyLoginAttempts($request)) {
        $this->fireLockoutEvent($request);

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

  //ADD THIS SECTION ONLY
  //SECTION STARTS
  // CHECK IF USER EXISTS IN OUR USER TABLE.
  if ($this->guard()->validate($this->credentials($request))) {
    //IF USER EXISTS, FIND USER USING EMAIL FROM REQUEST
    $user = User::where('email', $request->email)->first();
    //CHECK STATUS OF USER (HERE, 1 = ACTIVE & 0 = INACTIVE)
    if ($user->status===0) {
        //THROW ERROR WITH CUSTOM MESSAGE
        throw ValidationException::withMessages([$this->username() => __('User account has been deactivated.')]);
    }
  }
  //SECTION ENDS

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