没有全局范围的Laravel身份验证

时间:2016-07-08 12:10:29

标签: laravel authentication

在我的Laravel应用中,用户可以禁用(不删除)他们的帐户以从网站上消失。但是,如果他们尝试再次登录,则应自动激活他们的帐户,他们应该成功登录。

这是通过" active" users表中的列和User模型中的全局范围:

protected static function boot() {
    parent::boot();

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

现在的问题是那些非活动帐户无法再次登录,因为AuthController找不到它们(超出范围)。

我需要实现的目标:

  1. 让AuthController忽略全局范围"激活"。
  2. 如果用户名和密码正确,则更改"有效"列值为" 1"。
  3. 我现在的想法是使用withoutGlobalScope找到用户,手动验证密码,更改列"活动"到1,然后进行常规登录。

    在我的authController中使用postLogin方法:

    $user = User::withoutGlobalScope('active')
                ->where('username', $request->username)
                ->first();
    
    if($user != null) {
        if (Hash::check($request->username, $user->password))
        {
            // Set active column to 1
        }
    }
    
    return $this->login($request);
    

    所以问题是如何在不改变Laravel主代码的情况下使AuthController忽略全局范围,因此它将保留更新?

    感谢。

7 个答案:

答案 0 :(得分:0)

创建一个扩展[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public ActionResult NuevoProveedor(HttpPostedFileBase file, SubirArchivoModelo model) { SubirArchivoModelo modelo = new SubirArchivoModelo(); if (file != null) { string Ruta = file.FileName; return View(); } else { ViewBag.error = "No se pudo generar la carpeta, comunicate con Soporte Tecnico"; return View("UsuarioNuevo"); } } 的类GlobalUserProvider,如下所示

EloquentUserProvider

class GlobalUserProvider extends EloquentUserProvider { public function createModel() { $model = parent::createModel(); return $model->withoutGlobalScope('active'); } } 中注册您的新用户提供商:

AuthServiceProvider

最后,您应该在Auth::provider('globalUserProvider', function ($app, array $config) { return new GlobalUserProvider($this->app->make('hash'), $config['model']); }); 配置文件中将用户提供程序驱动程序更改为globalUserProvider。

auth.php

答案 1 :(得分:0)

protected static function boot() 
{
    parent::boot();
    if (\Auth::check()) {
        static::addGlobalScope('active', function(Builder $builder) {
            $builder->where('active', 1);
        });
    }
}

请尝试解决登录问题,您可以在登录后使用withoutGlobalScopes()进行激活。

答案 2 :(得分:0)

用您在OP中使用的代码扩展AuthController。应该可以。

public function postLogin(Request $request)
{
    $user = User::withoutGlobalScope('active')
                ->where('username', $request->username)
                ->first();

    if($user != null){
        if (Hash::check($request->password, $user->password)){
            $user->active = 1;
            $user->save();
        }
    }

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

答案 3 :(得分:0)

@Sasan的答案在Laravel 5.3中效果很好,但在5.4中效果不佳-createModel()期望一个Model但得到一个Builder对象,所以当EloquentUserProvider调用{{ 1}}引发异常:

$model->getAuthIdentifierName()

相反,请遵循相同的方法,但要覆盖更多功能,以便从BadMethodCallException: Call to undefined method Illuminate\Database\Query\Builder::getAuthIdentifierName() in /var/www/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2445 返回正确的对象。

createModel()返回不具有全局范围的构建器,该范围由其他两个函数使用。

getQuery()

答案 4 :(得分:0)

我通过创建新软件包来解决它。

mpyw/scoped-auth: Apply specific scope for user authentication.

运行clear = lambda: os.system('clear') clear() 并按如下所示修改您的用户模型:

composer require mpyw/scoped-auth

您还可以轻松选择<?php namespace App; use Illuminate\Auth\Authenticatable; use Illuminate\Contracts\Auth\Authenticatable as UserContract; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Mpyw\ScopedAuth\AuthScopable; class User extends Model implements UserContract, AuthScopable { use Authenticatable; public function scopeForAuthentication(Builder $query): Builder { return $query->withoutGlobalScope('active'); } } 在监听器上激活用户。

Illuminate\Auth\Events\Login

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        \Illuminate\Auth\Events\Login::class => [
            \App\Listeners\ActivateUser::class,
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        //
    }
}

答案 5 :(得分:0)

Sasan Farrokh的回答正确。唯一不用重写 createModel 而是重写 newModelQuery 的方法就可以了

protected function newModelQuery($model = null)
{
    $modelQuery = parent::newModelQuery();
    return $modelQuery->withoutGlobalScope('active');
}

答案 6 :(得分:0)

我不得不使用 ->withoutGlobalScopes() 代替

为了让它工作